适配系统深色模式的图标颜色,修复之前的 MIUI 版本通知图标 Hook 失败的问题

This commit is contained in:
2022-01-30 20:51:15 +08:00
parent 362b553c24
commit 755570c00e
2 changed files with 122 additions and 69 deletions

View File

@@ -28,7 +28,6 @@ import android.graphics.Outline
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.graphics.drawable.Icon
import android.os.Build
import android.service.notification.StatusBarNotification
import android.util.Log
import android.view.View
@@ -39,10 +38,7 @@ import androidx.core.graphics.drawable.toBitmap
import com.fankes.miui.notify.hook.HookMedium.QQ_PACKAGE_NAME
import com.fankes.miui.notify.hook.HookMedium.SELF_PACKAGE_NAME
import com.fankes.miui.notify.hook.HookMedium.SYSTEMUI_PACKAGE_NAME
import com.fankes.miui.notify.utils.XPrefUtils
import com.fankes.miui.notify.utils.dp
import com.fankes.miui.notify.utils.isNotMIUI
import com.fankes.miui.notify.utils.round
import com.fankes.miui.notify.utils.*
import de.robv.android.xposed.*
import de.robv.android.xposed.callbacks.XC_LoadPackage
@@ -156,7 +152,7 @@ class HookMain : IXposedHookLoadPackage {
.invoke(null) as Context
/**
* Hook 通知栏小图标
* Hook 状态栏小图标
* 区分系统版本 - 由于每个系统版本的方法不一样这里单独拿出来进行 Hook
* @param param Hook Param
*/
@@ -184,6 +180,73 @@ class HookMain : IXposedHookLoadPackage {
}
}
/**
* Hook 通知栏小图标
* 区分系统版本 - 由于每个系统版本的方法不一样这里单独拿出来进行 Hook
* @param param Hook Param
* @param isNew 是否为新版方式
*/
private fun XC_LoadPackage.LoadPackageParam.hookNotifyIconOnSet(param: XC_MethodHook.MethodHookParam, isNew: Boolean) =
runWithoutError(error = "AutoSetAppIconOnSet") {
/** 获取通知对象 - 由于 MIUI 的版本迭代不规范性可能是空的 */
(param.args?.get(if (isNew) 2 else 1) as? StatusBarNotification?)?.let { notifyInstance ->
/** 获取 [Context] */
val context = if (isNew) param.args[0] as Context else globalContext
/** 新版风格反色 */
val newStyle = if (context.isSystemInDarkMode) 0xFF2D2D2D.toInt() else Color.WHITE
/** 旧版风格反色 */
val oldStyle = if (context.isNotSystemInDarkMode) 0xFF515151.toInt() else Color.WHITE
/** 获取图标框 */
val iconImageView = param.args[if (isNew) 1 else 0] as ImageView
/** 获取通知小图标 */
val iconDrawable = notifyInstance.notification.smallIcon.loadDrawable(context)
/** 获取发送通知的 APP */
val packageName = notifyInstance.opPkg
/** 如果开启了修复聊天 APP 的图标 */
if (packageName == QQ_PACKAGE_NAME &&
XPrefUtils.getBoolean(HookMedium.ENABLE_CHAT_ICON_HOOK, default = true)
)
iconImageView.apply {
/** 设置自定义小图标 */
setImageDrawable(BitmapDrawable(IconPackParams.qqSmallIcon))
/** 上色 */
setColorFilter(if (isUpperOfAndroidS) newStyle else oldStyle)
}
else {
/** 重新设置图标 - 防止系统更改它 */
iconImageView.setImageDrawable(iconDrawable)
/** 判断如果是灰度图标就给他设置一个白色颜色遮罩 */
if (isGrayscaleIcon(context, iconDrawable))
iconImageView.setColorFilter(if (isUpperOfAndroidS) newStyle else oldStyle)
else
iconImageView.apply {
clipToOutline = true
/** 设置一个圆角轮廓裁切 */
outlineProvider = object : ViewOutlineProvider() {
override fun getOutline(view: View, out: Outline) {
out.setRoundRect(
0,
0,
view.width,
view.height,
5.dp(context)
)
}
}
/** 清除原生的背景边距设置 */
if (isUpperOfAndroidS) setPadding(0, 0, 0, 0)
/** 清除原生的主题色背景圆圈颜色 */
if (isUpperOfAndroidS) setBackgroundDrawable(null)
}
}
}
}
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
if (lpparam == null) return
when (lpparam.packageName) {
@@ -276,8 +339,41 @@ class HookMain : IXposedHookLoadPackage {
}
)
}
/** 修复下拉通知图标自动设置回 APP 图标的方法 - 新版本 */
runWithoutError(ignored = true) {
XposedHelpers.findAndHookMethod(
NotificationHeaderViewWrapperInjectorClass,
lpparam.classLoader,
"setAppIcon",
Context::class.java,
ImageView::class.java,
lpparam.findClass(ExpandedNotificationClass),
object : XC_MethodReplacement() {
override fun replaceHookedMethod(param: MethodHookParam): Any? {
lpparam.hookNotifyIconOnSet(param, isNew = true)
return null
}
}
)
}
/** 修复下拉通知图标自动设置回 APP 图标的方法 - 旧版本 */
runWithoutError(ignored = true) {
XposedHelpers.findAndHookMethod(
NotificationHeaderViewWrapperInjectorClass,
lpparam.classLoader,
"setAppIcon",
ImageView::class.java,
lpparam.findClass(ExpandedNotificationClass),
object : XC_MethodReplacement() {
override fun replaceHookedMethod(param: MethodHookParam): Any? {
lpparam.hookNotifyIconOnSet(param, isNew = false)
return null
}
}
)
}
/** 干掉下拉通知图标自动设置回 APP 图标的方法 - Android 12 */
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R)
if (isUpperOfAndroidS)
runWithoutError(error = "ResetIconBgAndPaddings") {
XposedHelpers.findAndHookMethod(
NotificationHeaderViewWrapperInjectorClass,
@@ -288,68 +384,6 @@ class HookMain : IXposedHookLoadPackage {
replaceToNull
)
}
/** 修复下拉通知图标自动设置回 APP 图标的方法 - Android 12 */
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R)
runWithoutError(error = "AutoSetAppIcon") {
XposedHelpers.findAndHookMethod(
NotificationHeaderViewWrapperInjectorClass,
lpparam.classLoader,
"setAppIcon",
Context::class.java,
ImageView::class.java,
lpparam.findClass(ExpandedNotificationClass),
object : XC_MethodReplacement() {
override fun replaceHookedMethod(param: MethodHookParam): Any? {
runWithoutError(error = "AutoSetAppIconOnSet") {
/** 获取 [Context] */
val context = param.args[0] as Context
/** 获取图标框 */
val iconImageView = param.args[1] as ImageView
/** 获取通知小图标 */
val iconDrawable = (param.args[2] as StatusBarNotification)
.notification.smallIcon.loadDrawable(context)
/** 获取发送通知的 APP */
val packageName = (param.args[2] as StatusBarNotification).opPkg
/** 如果开启了修复聊天 APP 的图标 */
if (packageName == QQ_PACKAGE_NAME &&
XPrefUtils.getBoolean(HookMedium.ENABLE_CHAT_ICON_HOOK, default = true)
)
iconImageView.apply {
/** 设置自定义小图标 */
setImageDrawable(BitmapDrawable(IconPackParams.qqSmallIcon))
/** 上色 */
setColorFilter(Color.WHITE)
}
else {
/** 重新设置图标 - 防止系统更改它 */
iconImageView.setImageDrawable(iconDrawable)
/** 判断如果是灰度图标就给他设置一个白色颜色遮罩 */
if (lpparam.isGrayscaleIcon(context, iconDrawable))
iconImageView.setColorFilter(Color.WHITE)
else
iconImageView.apply {
clipToOutline = true
/** 设置一个圆角轮廓裁切 */
outlineProvider = object : ViewOutlineProvider() {
override fun getOutline(view: View, out: Outline) {
out.setRoundRect(0, 0, view.width, view.height, 5.dp(context))
}
}
/** 清除原生的背景边距设置 */
setPadding(0, 0, 0, 0)
/** 清除原生的主题色背景圆圈颜色 */
setBackgroundDrawable(null)
}
}
}
return null
}
}
)
}
logD("hook Completed!")
}
}

View File

@@ -28,6 +28,7 @@ import android.content.pm.PackageManager
import android.content.res.Configuration
import android.graphics.*
import android.graphics.Bitmap.createBitmap
import android.os.Build
import android.util.Base64
import com.fankes.miui.notify.application.MNvApplication.Companion.appContext
import java.io.DataInputStream
@@ -46,6 +47,24 @@ val isSystemInDarkMode
*/
inline val isNotSystemInDarkMode get() = !isSystemInDarkMode
/**
* 系统深色模式是否开启
* @return [Boolean] 是否开启
*/
val Context.isSystemInDarkMode get() = (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES
/**
* 系统深色模式是否没开启
* @return [Boolean] 是否开启
*/
inline val Context.isNotSystemInDarkMode get() = !isSystemInDarkMode
/**
* 系统版本是否高于或等于 Android 12
* @return [Boolean] 是否符合条件
*/
inline val isUpperOfAndroidS get() = Build.VERSION.SDK_INT > Build.VERSION_CODES.R
/**
* 当前设备是否是 MIUI 定制 Android 系统
* @return [Boolean] 是否符合条件