修复 Android 11 MIUI 旧版本通知图标的问题

This commit is contained in:
2022-01-30 20:14:30 +08:00
parent 20210166c5
commit 362b553c24
2 changed files with 73 additions and 39 deletions

View File

@@ -29,7 +29,7 @@ android {
buildTypes { buildTypes {
release { release {
minifyEnabled true minifyEnabled false // break
signingConfig signingConfigs.debug signingConfig signingConfigs.debug
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }

View File

@@ -88,17 +88,19 @@ class HookMain : IXposedHookLoadPackage {
/** /**
* 忽略异常运行 * 忽略异常运行
* @param error 错误信息
* @param ignored 忽略后出错将不输出到控制台
* @param it 正常回调 * @param it 正常回调
*/ */
private fun runWithoutError(error: String, it: () -> Unit) { private fun runWithoutError(error: String = "", ignored: Boolean = false, it: () -> Unit) {
try { try {
it() it()
} catch (e: Error) { } catch (e: Error) {
logE("hookFailed: $error", e) if (!ignored) logE("hookFailed: $error", e)
} catch (e: Exception) { } catch (e: Exception) {
logE("hookFailed: $error", e) if (!ignored) logE("hookFailed: $error", e)
} catch (e: Throwable) { } catch (e: Throwable) {
logE("hookFailed: $error", e) if (!ignored) logE("hookFailed: $error", e)
} }
} }
@@ -153,6 +155,35 @@ class HookMain : IXposedHookLoadPackage {
.getDeclaredMethod("getContext").apply { isAccessible = true } .getDeclaredMethod("getContext").apply { isAccessible = true }
.invoke(null) as Context .invoke(null) as Context
/**
* Hook 通知栏小图标
* 区分系统版本 - 由于每个系统版本的方法不一样这里单独拿出来进行 Hook
* @param param Hook Param
*/
private fun XC_LoadPackage.LoadPackageParam.hookSmallIconOnSet(param: XC_MethodHook.MethodHookParam) =
runWithoutError(error = "GetSmallIconOnSet") {
/** 获取通知小图标 */
val iconDrawable = (param.result as Icon).loadDrawable(globalContext)
/** 获取通知对象 - 由于 MIUI 的版本迭代不规范性可能是空的 */
(param.args?.get(0) as? StatusBarNotification?)?.also { notifyInstance ->
/** 判断要设置的图标 */
when {
/** 如果开启了修复聊天 APP 的图标 */
notifyInstance.opPkg == QQ_PACKAGE_NAME &&
XPrefUtils.getBoolean(
HookMedium.ENABLE_CHAT_ICON_HOOK,
default = true
) ->
param.result = Icon.createWithBitmap(IconPackParams.qqSmallIcon)
/** 若不是灰度图标自动处理为圆角 */
!isGrayscaleIcon(globalContext, iconDrawable) ->
param.result = Icon.createWithBitmap(
iconDrawable.toBitmap().round(15.dp(globalContext))
)
}
}
}
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) { override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
if (lpparam == null) return if (lpparam == null) return
when (lpparam.packageName) { when (lpparam.packageName) {
@@ -171,7 +202,7 @@ class HookMain : IXposedHookLoadPackage {
/** 若没开启模块直接停止 Hook */ /** 若没开启模块直接停止 Hook */
if (!XPrefUtils.getBoolean(HookMedium.ENABLE_MODULE, default = true)) return if (!XPrefUtils.getBoolean(HookMedium.ENABLE_MODULE, default = true)) return
/** 强制回写系统的状态栏图标样式为原生 */ /** 强制回写系统的状态栏图标样式为原生 */
runWithoutError("SubstituteSmallIcon") { runWithoutError(error = "SubstituteSmallIcon") {
XposedHelpers.findAndHookMethod( XposedHelpers.findAndHookMethod(
NotificationUtilClass, NotificationUtilClass,
lpparam.classLoader, lpparam.classLoader,
@@ -181,7 +212,7 @@ class HookMain : IXposedHookLoadPackage {
) )
} }
/** 修复通知图标为彩色 */ /** 修复通知图标为彩色 */
runWithoutError("IgnoreStatusBarIconColor") { runWithoutError(error = "IgnoreStatusBarIconColor") {
XposedHelpers.findAndHookMethod( XposedHelpers.findAndHookMethod(
NotificationUtilClass, NotificationUtilClass,
lpparam.classLoader, lpparam.classLoader,
@@ -191,18 +222,21 @@ class HookMain : IXposedHookLoadPackage {
override fun replaceHookedMethod(param: MethodHookParam) = override fun replaceHookedMethod(param: MethodHookParam) =
if (XPrefUtils.getBoolean(HookMedium.ENABLE_COLOR_ICON_HOOK, default = true)) if (XPrefUtils.getBoolean(HookMedium.ENABLE_COLOR_ICON_HOOK, default = true))
try { try {
/** 获取发送通知的 APP */ /** 获取通知对象 - 由于 MIUI 的版本迭代不规范性可能是空的 */
val packageName = (param.args[0] as StatusBarNotification).opPkg (param.args?.get(0) as? StatusBarNotification?)?.let { notifyInstance ->
/** 获取发送通知的 APP */
val packageName = notifyInstance.opPkg
/** 获取通知小图标 */ /** 获取通知小图标 */
val iconDrawable = (param.args[0] as StatusBarNotification) val iconDrawable =
.notification.smallIcon.loadDrawable(lpparam.globalContext) notifyInstance.notification.smallIcon.loadDrawable(lpparam.globalContext)
/** 如果开启了修复聊天 APP 的图标 */ /** 如果开启了修复聊天 APP 的图标 */
if (packageName == QQ_PACKAGE_NAME && if (packageName == QQ_PACKAGE_NAME &&
XPrefUtils.getBoolean(HookMedium.ENABLE_CHAT_ICON_HOOK, default = true) XPrefUtils.getBoolean(HookMedium.ENABLE_CHAT_ICON_HOOK, default = true)
) false ) false
/** 只要不是灰度就返回彩色图标 */ /** 只要不是灰度就返回彩色图标 */
else !lpparam.isGrayscaleIcon(lpparam.globalContext, iconDrawable) else !lpparam.isGrayscaleIcon(lpparam.globalContext, iconDrawable)
} ?: true // 否则不对颜色进行反色处理防止一些系统图标出现异常
} catch (e: Exception) { } catch (e: Exception) {
logE("Failed to hook ignoreStatusBarIconColor", e) logE("Failed to hook ignoreStatusBarIconColor", e)
false false
@@ -211,8 +245,8 @@ class HookMain : IXposedHookLoadPackage {
} }
) )
} }
/** 强制回写系统的状态栏图标样式为原生 */ /** 强制回写系统的状态栏图标样式为原生 - 新版 */
runWithoutError("GetSmallIcon") { runWithoutError(ignored = true) {
XposedHelpers.findAndHookMethod( XposedHelpers.findAndHookMethod(
NotificationUtilClass, NotificationUtilClass,
lpparam.classLoader, lpparam.classLoader,
@@ -222,29 +256,29 @@ class HookMain : IXposedHookLoadPackage {
object : XC_MethodHook() { object : XC_MethodHook() {
override fun afterHookedMethod(param: MethodHookParam) { override fun afterHookedMethod(param: MethodHookParam) {
runWithoutError("GetSmallIconOnSet") { lpparam.hookSmallIconOnSet(param)
/** 获取通知小图标 */ }
val iconDrawable = (param.result as Icon).loadDrawable(lpparam.globalContext) }
/** 判断要设置的图标 */ )
when { }
/** 如果开启了修复聊天 APP 的图标 */ /** 强制回写系统的状态栏图标样式为原生 - 旧版 */
(param.args[0] as StatusBarNotification).opPkg == QQ_PACKAGE_NAME && runWithoutError(ignored = true) {
XPrefUtils.getBoolean(HookMedium.ENABLE_CHAT_ICON_HOOK, default = true) -> XposedHelpers.findAndHookMethod(
param.result = Icon.createWithBitmap(IconPackParams.qqSmallIcon) NotificationUtilClass,
/** 若不是灰度图标自动处理为圆角 */ lpparam.classLoader,
!lpparam.isGrayscaleIcon(lpparam.globalContext, iconDrawable) -> "getSmallIcon",
param.result = Icon.createWithBitmap( lpparam.findClass(ExpandedNotificationClass),
iconDrawable.toBitmap().round(15.dp(lpparam.globalContext)) object : XC_MethodHook() {
)
} override fun afterHookedMethod(param: MethodHookParam) {
} lpparam.hookSmallIconOnSet(param)
} }
} }
) )
} }
/** 干掉下拉通知图标自动设置回 APP 图标的方法 - Android 12 */ /** 干掉下拉通知图标自动设置回 APP 图标的方法 - Android 12 */
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R)
runWithoutError("ResetIconBgAndPaddings") { runWithoutError(error = "ResetIconBgAndPaddings") {
XposedHelpers.findAndHookMethod( XposedHelpers.findAndHookMethod(
NotificationHeaderViewWrapperInjectorClass, NotificationHeaderViewWrapperInjectorClass,
lpparam.classLoader, lpparam.classLoader,
@@ -256,7 +290,7 @@ class HookMain : IXposedHookLoadPackage {
} }
/** 修复下拉通知图标自动设置回 APP 图标的方法 - Android 12 */ /** 修复下拉通知图标自动设置回 APP 图标的方法 - Android 12 */
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R)
runWithoutError("AutoSetAppIcon") { runWithoutError(error = "AutoSetAppIcon") {
XposedHelpers.findAndHookMethod( XposedHelpers.findAndHookMethod(
NotificationHeaderViewWrapperInjectorClass, NotificationHeaderViewWrapperInjectorClass,
lpparam.classLoader, lpparam.classLoader,
@@ -266,7 +300,7 @@ class HookMain : IXposedHookLoadPackage {
lpparam.findClass(ExpandedNotificationClass), lpparam.findClass(ExpandedNotificationClass),
object : XC_MethodReplacement() { object : XC_MethodReplacement() {
override fun replaceHookedMethod(param: MethodHookParam): Any? { override fun replaceHookedMethod(param: MethodHookParam): Any? {
runWithoutError("AutoSetAppIconOnSet") { runWithoutError(error = "AutoSetAppIconOnSet") {
/** 获取 [Context] */ /** 获取 [Context] */
val context = param.args[0] as Context val context = param.args[0] as Context