32 Commits
1.1 ... 1.25

Author SHA1 Message Date
485f85873c Update version to 1.25,fix more bugs. 2022-02-05 22:57:04 +08:00
8202239f57 通知优化图标展示界面顶部增加适配的图标个数展示 2022-02-05 22:39:19 +08:00
7e4cd7f71a 增加“下载管理程序”、“MIUI天气”、“米家”、“和平精英”、“起点读书”、“高德地图”、“百度地图”、“招商银行”、“人民日报”、“即可”通知优化图标 2022-02-05 22:30:53 +08:00
f6c4448eed 适配 MIUI 12,修复在 MIUI 12 上不生效的问题,加入最低 MIUI 版本判断 2022-02-05 21:42:35 +08:00
45dde844b7 Update version to 1.2,fix more bugs. 2022-02-03 22:04:09 +08:00
8e987897fc 增加帮助文案 2022-02-03 21:58:27 +08:00
60e2a5b6ea 增加模块设置缓存功能,防止通知图标过多造成下拉通知栏卡顿 2022-02-03 21:34:02 +08:00
8a31373ebd 优化代码 2022-02-03 21:27:18 +08:00
963933f168 修改“微信”通知优化小图标配置 2022-02-03 21:23:51 +08:00
a72e89e57c 增加“QQ邮箱”通知优化小图标 2022-02-03 21:23:17 +08:00
c40b1bf3ee 增加“多看阅读”、“闲鱼”、“美团”、“美团外卖”通知优化小图标 2022-02-03 21:19:19 +08:00
3045c90580 优化淘宝、抖音通知优化图标大小 2022-02-03 21:06:22 +08:00
8e9c0127fa 待发布版本 2022-02-02 15:59:47 +08:00
7da1949de3 默认关闭模块调试日志输出 2022-02-02 15:53:08 +08:00
1bbacad3d2 默认关闭模块调试日志输出 2022-02-02 15:52:46 +08:00
6e6b566ea1 优化 lamprose 提交的通知优化图标,增加“大众点评”、“小米视频”、“腾讯视频”、“QQ音乐”、“酷狗音乐”、“滴滴出行”、“菜鸟”通知优化图标 2022-02-02 15:51:57 +08:00
bf5cd8de2b 修复 2022-02-02 15:07:26 +08:00
Fankesyooni
ec5796f37e Merge pull request #2 from lamprose/master
增加”小米商城“,”饿了么“,”小米有品“,”携程“,”App分享“,”小米社区“,”网易云音乐“,”什么值得买“,”王者荣耀“通知优化图标
2022-02-02 02:50:39 +08:00
lamprose
51353caec2 增加”小米商城“,”饿了么“,”小米有品“,”携程“,”App分享“,”小米社区“,”网易云音乐“,”什么值得买“,”王者荣耀“通知优化图标 2022-02-02 02:28:17 +08:00
f3ca453a9a Fix a commit 2022-02-02 00:40:24 +08:00
29df754513 Update version to 1.15 fix more bugs. 2022-02-01 23:19:04 +08:00
cd60ec7ac4 修复一个执行顺序问题 2022-02-01 23:16:04 +08:00
4129794bbb 增加“快手”、“小红书”通知优化图标 2022-02-01 23:11:47 +08:00
7fc8d2828a 增加“知乎”、“浏览器”通知优化图标 2022-02-01 23:03:09 +08:00
780e78909a 增加“智能服务”通知优化图标 2022-02-01 22:54:22 +08:00
b40cb86d77 增加“智能服务”通知优化图标 2022-02-01 22:50:57 +08:00
2ab36dd2f3 修复一个问题 2022-02-01 22:48:27 +08:00
95160d30b3 关闭混淆功能 2022-02-01 22:44:00 +08:00
5c42934bf2 增加调试日志功能 2022-02-01 22:41:04 +08:00
e939121d86 增加“音质音效”通知优化图标 2022-02-01 22:25:56 +08:00
f243a0de76 增加详细模块运行日志并改善 Hook 方案 2022-02-01 22:16:49 +08:00
97757c3d65 增加详细模块运行日志并改善 Hook 方案 2022-02-01 22:15:42 +08:00
12 changed files with 1512 additions and 272 deletions

View File

@@ -2,7 +2,7 @@
![Eclipse Marketplace](https://img.shields.io/badge/build-passing-brightgreen)
![Eclipse Marketplace](https://img.shields.io/badge/license-GPL3.0-blue)
![Eclipse Marketplace](https://img.shields.io/badge/version-v1.1-green)
![Eclipse Marketplace](https://img.shields.io/badge/version-v1.25-green)
<br/><br/>
<img src="https://github.com/fankes/MIUINativeNotifyIcon/blob/master/app/src/main/ic_launcher-playstore.png" width = "100" height = "100"/>
<br/>
@@ -12,12 +12,13 @@ Fix the native notification bar icon function abandoned by the MIUI development
# 开始使用
点击下载最新版本
<a href='https://github.com/fankes/MIUINativeNotifyIcon/releases'>![Eclipse Marketplace](https://img.shields.io/badge/download-v1.1-green)</a>
<a href='https://github.com/fankes/MIUINativeNotifyIcon/releases'>![Eclipse Marketplace](https://img.shields.io/badge/download-v1.25-green)</a>
<br/><br/>
⚠️ 适配说明<br/>
- 此模块仅支持 Lsposed(作用域“系统界面”)、EdXposed(不推荐)、不支持太极无极(阴)
- 目前最低支持基于 Android 9 版本的 MIUI12 或 MIUI12.5(建议)
- 使用 Zygisk 方式运行的 Lsposed 可能会发生 Hook 不生效的问题,若出现问题请使用 Ramdisk 版本的 Lsposed
# 禁止任何商业用途
@@ -59,7 +60,7 @@ com.android.internal.util.ContrastColorUtil
- 这个类中有一个方法可以拿出来判断图标的灰度效果
```java
```
ContrastColorUtil.getInstance().isGrayscaleIcon(drawable);
```

View File

@@ -21,8 +21,8 @@ android {
applicationId "com.fankes.miui.notify"
minSdk 26
targetSdk 26
versionCode 2
versionName "1.1"
versionCode 5
versionName "1.25"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

View File

@@ -18,7 +18,7 @@
*
* This file is Created by fankes on 2022/01/24.
*/
@file:Suppress("SameParameterValue")
@file:Suppress("SameParameterValue", "DEPRECATION")
package com.fankes.miui.notify.hook
@@ -47,18 +47,24 @@ class HookMain : IXposedHookLoadPackage {
companion object {
private const val NotificationUtilClass =
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationUtil"
private const val SystemUIApplicationClass = "$SYSTEMUI_PACKAGE_NAME.SystemUIApplication"
private const val NotificationHeaderViewWrapperInjectorClass =
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.row.wrapper.NotificationHeaderViewWrapperInjector"
private const val ExpandedNotificationClass =
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.ExpandedNotification"
private const val SystemUIApplicationClass = "$SYSTEMUI_PACKAGE_NAME.SystemUIApplication"
private const val StatusBarIconViewClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.StatusBarIconView"
private const val ContrastColorUtilClass = "com.android.internal.util.ContrastColorUtil"
private val NotificationUtilClass = Pair(
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationUtil",
"$SYSTEMUI_PACKAGE_NAME.miui.statusbar.notification.NotificationUtil"
)
private val ExpandedNotificationClass = Pair(
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.ExpandedNotification",
"$SYSTEMUI_PACKAGE_NAME.miui.statusbar.ExpandedNotification"
)
}
/** 仅作用于替换的 Hook 方法体 */
@@ -85,26 +91,24 @@ class HookMain : IXposedHookLoadPackage {
/**
* 忽略异常运行
* @param error 错误信息
* @param ignored 忽略后出错将不输出到控制台
* @param it 正常回调
*/
private fun runWithoutError(error: String = "", ignored: Boolean = false, it: () -> Unit) {
private fun runWithoutError(error: String = "", it: () -> Unit) {
try {
it()
} catch (e: Error) {
if (!ignored) logE("hookFailed: $error", e)
} catch (e: Exception) {
if (!ignored) logE("hookFailed: $error", e)
} catch (e: Throwable) {
if (!ignored) logE("hookFailed: $error", e)
logE(content = "hookFailed: $error", e)
}
}
/**
* Print the log
* @param content
* @param it 继续执行的方法
*/
private fun logD(content: String) {
private fun logD(content: String, it: () -> Unit = {}) {
it()
if (!HookMedium.getBoolean(HookMedium.ENABLE_MODULE_LOG, default = false)) return
XposedBridge.log("[MIUINativeNotifyIcon][D]>$content")
Log.d("MIUINativeNotifyIcon", content)
}
@@ -112,13 +116,84 @@ class HookMain : IXposedHookLoadPackage {
/**
* Print the log
* @param content
* @param it 继续执行的方法
*/
private fun logE(content: String, e: Throwable? = null) {
private fun logW(content: String, it: () -> Unit = {}) {
it()
if (!HookMedium.getBoolean(HookMedium.ENABLE_MODULE_LOG, default = false)) return
XposedBridge.log("[MIUINativeNotifyIcon][W]>$content")
Log.d("MIUINativeNotifyIcon", content)
}
/**
* Print the log
* @param content
* @param e 异常
* @param it 继续执行的方法
*/
private fun logE(content: String, e: Throwable? = null, it: () -> Unit = {}) {
it()
XposedBridge.log("[MIUINativeNotifyIcon][E]>$content")
XposedBridge.log(e)
Log.e("MIUINativeNotifyIcon", content, e)
}
/**
* 目标类是否存在
* @param name 类名
* @return [Boolean]
*/
private fun XC_LoadPackage.LoadPackageParam.isClassExist(name: String) = try {
classLoader.loadClass(name)
true
} catch (_: Throwable) {
false
}
/**
* 目标方法是否存在
* @param classPair 类数组
* @param name 方法名
* @param param 方法参数类型数组
* @return [Boolean]
*/
private fun XC_LoadPackage.LoadPackageParam.isMethodExist(
classPair: Pair<String, String>,
name: String, vararg param: Class<*>
) = try {
(try {
classLoader.loadClass(classPair.first)
} catch (_: Throwable) {
try {
classLoader.loadClass(classPair.second)
} catch (_: Throwable) {
null
}
})?.getDeclaredMethod(name, *param)
true
} catch (_: Throwable) {
false
}
/**
* 目标方法是否存在
* @param className 类名
* @param name 方法名
* @param param 方法参数类型数组
* @return [Boolean]
*/
private fun XC_LoadPackage.LoadPackageParam.isMethodExist(className: String, name: String, vararg param: Class<*>) =
try {
(try {
classLoader.loadClass(className)
} catch (_: Throwable) {
null
})?.getDeclaredMethod(name, *param)
true
} catch (_: Throwable) {
false
}
/**
* 查找目标类
* @param name 类名
@@ -127,6 +202,40 @@ class HookMain : IXposedHookLoadPackage {
private fun XC_LoadPackage.LoadPackageParam.findClass(name: String) =
classLoader.loadClass(name)
/**
* 查找目标类 - 两个类都没找到才会报错
* @param pair 类名数组
* @return [Class]
*/
private fun XC_LoadPackage.LoadPackageParam.findClass(pair: Pair<String, String>) = try {
classLoader.loadClass(pair.first)
} catch (_: Throwable) {
try {
classLoader.loadClass(pair.second)
} catch (e: Throwable) {
logE(content = "Cannot find Class ${pair.first} and ${pair.second}", e)
error("[Throwable] Cannot find Class ${pair.first} and ${pair.second}")
}
}
/**
* 存在目标类的类名 - 两个类都没找到会抛出异常
* @param pair 类名数组
* @return [String] 目标类名
*/
private fun XC_LoadPackage.LoadPackageParam.existClass(pair: Pair<String, String>) = try {
classLoader.loadClass(pair.first)
pair.first
} catch (_: Throwable) {
try {
classLoader.loadClass(pair.second)
pair.second
} catch (_: Throwable) {
logE(content = "Cannot find Class ${pair.first} and ${pair.second}")
error("[Throwable] Cannot find Class ${pair.first} and ${pair.second}")
}
}
/**
* ⚠️ 这个是修复彩色图标的关键核心代码判断
* 判断是否为灰度图标 - 反射执行系统方法
@@ -147,10 +256,13 @@ class HookMain : IXposedHookLoadPackage {
* @param instance 通知实例
* @return [String]
*/
private fun XC_LoadPackage.LoadPackageParam.findAppName(instance: Any?) =
private fun XC_LoadPackage.LoadPackageParam.findAppName(instance: Any?) = try {
findClass(ExpandedNotificationClass).getDeclaredMethod("getAppName").let {
it.isAccessible = true
it.invoke(instance) as? String ?: ""
it.invoke(instance) as? String ?: "unknown"
}
} catch (_: Throwable) {
"unknown"
}
/**
@@ -194,14 +306,24 @@ class HookMain : IXposedHookLoadPackage {
when {
/** 如果开启了修复 APP 的彩色图标 */
customIcon != null && HookMedium.getBoolean(HookMedium.ENABLE_NOTIFY_ICON_HOOK, default = true) ->
param.result = customIcon
logD(
content = "GetSmallIconOnSet -> " +
"hook Custom AppIcon [pkgName] ${notifyInstance.opPkgName} " +
"[appName] ${findAppName(notifyInstance)}"
) { param.result = customIcon }
/** 若不是灰度图标自动处理为圆角 */
isNotGrayscaleIcon ->
logD(
content = "GetSmallIconOnSet -> " +
"hook Color AppIcon [pkgName] ${notifyInstance.opPkgName} " +
"[appName] ${findAppName(notifyInstance)}"
) {
param.result = Icon.createWithBitmap(
iconDrawable.toBitmap().round(15.dp(globalContext))
)
}
}
} ?: logW(content = "GetSmallIconOnSet -> StatusBarNotification got null")
}
/**
@@ -257,15 +379,25 @@ class HookMain : IXposedHookLoadPackage {
setImageBitmap(customIcon)
/** 上色 */
setColorFilter(if (isUpperOfAndroidS) newStyle else oldStyle)
/** 输出调试日志 */
logD(
content = "AutoSetAppIconOnSet -> " +
"hook Custom AppIcon [pkgName] ${notifyInstance.opPkgName} " +
"[appName] ${findAppName(notifyInstance)}"
)
}
else {
/** 重新设置图标 - 防止系统更改它 */
iconImageView.setImageDrawable(iconDrawable)
/*判断是否开启 Hook 彩色图标*/
/** 判断是否开启 Hook 彩色图标 */
if (isHookColorIcon) {
/** 判断如果是灰度图标就给他设置一个白色颜色遮罩 */
if (isGrayscaleIcon)
iconImageView.setColorFilter(if (isUpperOfAndroidS) newStyle else oldStyle)
logD(
content = "AutoSetAppIconOnSet -> " +
"hook Grayscale AppIcon [pkgName] ${notifyInstance.opPkgName} " +
"[appName] ${findAppName(notifyInstance)}"
) { iconImageView.setColorFilter(if (isUpperOfAndroidS) newStyle else oldStyle) }
else
iconImageView.apply {
clipToOutline = true
@@ -273,11 +405,8 @@ class HookMain : IXposedHookLoadPackage {
outlineProvider = object : ViewOutlineProvider() {
override fun getOutline(view: View, out: Outline) {
out.setRoundRect(
0,
0,
view.width,
view.height,
5.dp(context)
0, 0,
view.width, view.height, 5.dp(context)
)
}
}
@@ -285,36 +414,121 @@ class HookMain : IXposedHookLoadPackage {
if (isUpperOfAndroidS) setPadding(0, 0, 0, 0)
/** 清除原生的主题色背景圆圈颜色 */
if (isUpperOfAndroidS) background = null
/** 输出调试日志 */
logD(
content = "AutoSetAppIconOnSet -> " +
"hook Color AppIcon [pkgName] ${notifyInstance.opPkgName} " +
"[appName] ${findAppName(notifyInstance)}"
)
}
/** 否则一律设置灰度图标 */
} else iconImageView.setColorFilter(if (isUpperOfAndroidS) newStyle else oldStyle)
} else
logD(
content = "AutoSetAppIconOnSet -> " +
"hook NonColor AppIcon [pkgName] ${notifyInstance.opPkgName} " +
"[appName] ${findAppName(notifyInstance)}"
) { iconImageView.setColorFilter(if (isUpperOfAndroidS) newStyle else oldStyle) }
}
} ?: logW(content = "AutoSetAppIconOnSet -> StatusBarNotification got null")
}
/**
* Hook 通知栏小图标颜色
* 区分系统版本 - 由于每个系统版本的方法不一样这里单独拿出来进行 Hook
* @param expandedNf 状态栏实例
* @return [Boolean] 是否忽略通知图标颜色
*/
private fun XC_LoadPackage.LoadPackageParam.hookIgnoreStatusBarIconColor(expandedNf: StatusBarNotification?) =
if (HookMedium.getBoolean(HookMedium.ENABLE_COLOR_ICON_HOOK, default = true))
try {
/** 获取通知对象 - 由于 MIUI 的版本迭代不规范性可能是空的 */
expandedNf?.let { notifyInstance ->
/** 获取通知小图标 */
val iconDrawable =
notifyInstance.notification.smallIcon.loadDrawable(globalContext)
/** 判断是否不是灰度图标 */
val isNotGrayscaleIcon = !isGrayscaleIcon(globalContext, iconDrawable)
/** 获取目标修复彩色图标的 APP */
var isTargetApp = false
run {
IconPackParams.iconDatas.forEach {
if ((notifyInstance.opPkgName == it.packageName ||
findAppName(notifyInstance) == it.appName) &&
HookMedium.isAppNotifyHookOf(it)
) {
if (isNotGrayscaleIcon || HookMedium.isAppNotifyHookAllOf(it)) isTargetApp = true
return@run
}
}
}
/** 如果开启了修复 APP 的彩色图标 */
if (isTargetApp && HookMedium.getBoolean(HookMedium.ENABLE_NOTIFY_ICON_HOOK, default = true)) let {
logD(
content = "IgnoreStatusBarIconColor -> " +
"hook Color AppIcon [pkgName] ${notifyInstance.opPkgName} " +
"[appName] ${findAppName(notifyInstance)}"
)
false
}
else let {
logD(
content = "IgnoreStatusBarIconColor -> " +
"hook Grayscale[${!isNotGrayscaleIcon}] AppIcon " +
"[pkgName] ${notifyInstance.opPkgName} " +
"[appName] ${findAppName(notifyInstance)}"
)
/** 只要不是灰度就返回彩色图标 */
isNotGrayscaleIcon
}
} ?: let {
logW(content = "IgnoreStatusBarIconColor -> StatusBarNotification got null")
/** 否则不对颜色进行反色处理防止一些系统图标出现异常 */
true
}
} catch (e: Exception) {
logE("Failed to hook ignoreStatusBarIconColor", e)
false
}
else let {
logD(content = "IgnoreStatusBarIconColor -> hook NonColor AppIcon")
false
}
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
if (lpparam == null) return
when (lpparam.packageName) {
/** Hook 自身 */
SELF_PACKAGE_NAME ->
runWithoutError(error = "HookModuleSelf") {
XposedHelpers.findAndHookMethod(
"$SELF_PACKAGE_NAME.hook.HookMedium",
lpparam.classLoader,
"isHooked",
replaceToTrue
)
}
/** Hook 系统 UI */
SYSTEMUI_PACKAGE_NAME -> {
/** 若不是 MIUI 系统直接停止 Hook */
if (isNotMIUI) return
/** 系统版本过低直接停止 Hook */
if (isLowerAndroidP) return
/** 若没开启模块直接停止 Hook */
if (!HookMedium.getBoolean(HookMedium.ENABLE_MODULE, default = true)) return
SYSTEMUI_PACKAGE_NAME ->
when {
/** 不是 MIUI 系统停止 Hook */
isNotMIUI ->
logW(content = "Aborted Hook -> This System is not MIUI")
/** 系统版本低于 Android P 停止 Hook */
isLowerAndroidP ->
logW(content = "Aborted Hook -> This System is lower than Android P")
/** 不是支持的 MIUI 系统停止 Hook */
isNotSupportMiuiVersion ->
logW(content = "Aborted Hook -> This MIUI Version $miuiVersion not supported")
/** Hook 被手动关闭停止 Hook */
!HookMedium.getBoolean(HookMedium.ENABLE_MODULE, default = true) ->
logW(content = "Aborted Hook -> Hook Closed")
else -> {
/** 强制回写系统的状态栏图标样式为原生 */
runWithoutError(error = "SubstituteSmallIcon") {
XposedHelpers.findAndHookMethod(
NotificationUtilClass,
lpparam.existClass(NotificationUtilClass),
lpparam.classLoader,
"shouldSubstituteSmallIcon",
lpparam.findClass(ExpandedNotificationClass),
@@ -322,122 +536,120 @@ class HookMain : IXposedHookLoadPackage {
)
}
/** 修复通知图标为彩色 */
if (lpparam.isMethodExist(NotificationUtilClass, name = "ignoreStatusBarIconColor"))
runWithoutError(error = "IgnoreStatusBarIconColor") {
XposedHelpers.findAndHookMethod(
NotificationUtilClass,
lpparam.existClass(NotificationUtilClass),
lpparam.classLoader,
"ignoreStatusBarIconColor",
lpparam.findClass(ExpandedNotificationClass),
object : XC_MethodReplacement() {
override fun replaceHookedMethod(param: MethodHookParam) =
if (HookMedium.getBoolean(HookMedium.ENABLE_COLOR_ICON_HOOK, default = true))
lpparam.hookIgnoreStatusBarIconColor(param.args?.get(0) as? StatusBarNotification?)
}
)
}
else
runWithoutError(error = "UpdateIconColor") {
XposedHelpers.findAndHookMethod(
StatusBarIconViewClass,
lpparam.classLoader, "updateIconColor",
object : XC_MethodHook() {
override fun afterHookedMethod(param: MethodHookParam) =
runWithoutError(error = "UpdateIconColorOnSet") {
/** 是否忽略图标颜色 */
val isIgnoredColor = lpparam.hookIgnoreStatusBarIconColor(
param.thisObject.javaClass.getDeclaredField("mNotification").apply {
isAccessible = true
}[param.thisObject] as? StatusBarNotification?
)
/** 当前着色颜色 */
val currentColor =
param.thisObject.javaClass.getDeclaredField("mCurrentSetColor").apply {
isAccessible = true
}[param.thisObject] as? Int ?: Color.WHITE
/** 判断并设置颜色 */
if (isIgnoredColor)
(param.thisObject as? ImageView?)?.colorFilter = null
else (param.thisObject as? ImageView?)?.setColorFilter(currentColor)
logD(content = "IgnoreStatusBarIconColor[UseOldWay] -> isIgnored[$isIgnoredColor]")
}
}
)
}
/** 强制回写系统的状态栏图标样式为原生 */
runWithoutError(error = "GetSmallIcon") {
try {
/** 获取通知对象 - 由于 MIUI 的版本迭代不规范性可能是空的 */
(param.args?.get(0) as? StatusBarNotification?)?.let { notifyInstance ->
/** 获取通知小图标 */
val iconDrawable =
notifyInstance.notification.smallIcon.loadDrawable(lpparam.globalContext)
/** 判断是否不是灰度图标 */
val isNotGrayscaleIcon =
!lpparam.isGrayscaleIcon(lpparam.globalContext, iconDrawable)
/** 获取目标修复彩色图标的 APP */
var isTargetApp = false
run {
IconPackParams.iconDatas.forEach {
if ((notifyInstance.opPkgName == it.packageName ||
lpparam.findAppName(notifyInstance) == it.appName) &&
HookMedium.isAppNotifyHookOf(it)
) {
if (isNotGrayscaleIcon || HookMedium.isAppNotifyHookAllOf(it))
isTargetApp = true
return@run
}
}
}
/** 如果开启了修复 APP 的彩色图标 */
if (isTargetApp &&
HookMedium.getBoolean(HookMedium.ENABLE_NOTIFY_ICON_HOOK, default = true)
) false
/** 只要不是灰度就返回彩色图标 */
else isNotGrayscaleIcon
} ?: true // 否则不对颜色进行反色处理防止一些系统图标出现异常
} catch (e: Exception) {
logE("Failed to hook ignoreStatusBarIconColor", e)
false
}
else false
}
)
}
/** 强制回写系统的状态栏图标样式为原生 - 新版 */
runWithoutError(ignored = true) {
XposedHelpers.findAndHookMethod(
NotificationUtilClass,
lpparam.classLoader,
/** 新版方法 */
lpparam.findClass(NotificationUtilClass)
.getDeclaredMethod(
"getSmallIcon",
lpparam.findClass(ExpandedNotificationClass),
Int::class.java,
object : XC_MethodHook() {
Int::class.java
).apply { isAccessible = true }
} catch (_: Throwable) {
try {
/** 旧版方法 */
lpparam.findClass(NotificationUtilClass)
.getDeclaredMethod("getSmallIcon", lpparam.findClass(ExpandedNotificationClass))
.apply { isAccessible = true }
} catch (_: Throwable) {
/** 超旧版方法 */
lpparam.findClass(NotificationUtilClass)
.getDeclaredMethod(
"getSmallIcon",
Context::class.java,
lpparam.findClass(ExpandedNotificationClass)
).apply { isAccessible = true }
}
}.also {
XposedBridge.hookMethod(it, object : XC_MethodHook() {
override fun afterHookedMethod(param: MethodHookParam) {
lpparam.hookSmallIconOnSet(param)
}
}
)
}
/** 强制回写系统的状态栏图标样式为原生 - 旧版 */
runWithoutError(ignored = true) {
XposedHelpers.findAndHookMethod(
NotificationUtilClass,
lpparam.classLoader,
"getSmallIcon",
lpparam.findClass(ExpandedNotificationClass),
object : XC_MethodHook() {
override fun afterHookedMethod(param: MethodHookParam) {
lpparam.hookSmallIconOnSet(param)
})
}
}
)
}
/** 修复下拉通知图标自动设置回 APP 图标的方法 - 新版本 */
runWithoutError(ignored = true) {
XposedHelpers.findAndHookMethod(
NotificationHeaderViewWrapperInjectorClass,
lpparam.classLoader,
/** 修复下拉通知图标自动设置回 APP 图标的方法 */
if (lpparam.isClassExist(NotificationHeaderViewWrapperInjectorClass))
runWithoutError(error = "AutoSetAppIcon") {
var isNewWay = true
try {
/** 新版方法 */
lpparam.findClass(NotificationHeaderViewWrapperInjectorClass)
.getDeclaredMethod(
"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,
lpparam.findClass(ExpandedNotificationClass)
).apply { isAccessible = true }
} catch (_: Throwable) {
isNewWay = false
/** 旧版方法 */
lpparam.findClass(NotificationHeaderViewWrapperInjectorClass)
.getDeclaredMethod(
"setAppIcon",
ImageView::class.java,
lpparam.findClass(ExpandedNotificationClass),
object : XC_MethodReplacement() {
lpparam.findClass(ExpandedNotificationClass)
).apply { isAccessible = true }
}.also {
XposedBridge.hookMethod(it, object : XC_MethodReplacement() {
override fun replaceHookedMethod(param: MethodHookParam): Any? {
lpparam.hookNotifyIconOnSet(param, isNew = false)
lpparam.hookNotifyIconOnSet(param, isNew = isNewWay)
return null
}
})
}
)
}
else logW(content = "Your MIUI Version $miuiVersion is too old and not support for RowsIcon")
/** 干掉下拉通知图标自动设置回 APP 图标的方法 - Android 12 */
if (isUpperOfAndroidS)
runWithoutError(error = "ResetIconBgAndPaddings") {
if (isUpperOfAndroidS &&
lpparam.isMethodExist(
NotificationHeaderViewWrapperInjectorClass,
name = "resetIconBgAndPaddings"
)
) runWithoutError(error = "ResetIconBgAndPaddings") {
XposedHelpers.findAndHookMethod(
NotificationHeaderViewWrapperInjectorClass,
lpparam.classLoader,
@@ -447,7 +659,8 @@ class HookMain : IXposedHookLoadPackage {
replaceToNull
)
}
logD("hook Completed!")
logD(content = "hook Completed!")
}
}
}
}

View File

@@ -38,6 +38,7 @@ import java.io.File
object HookMedium {
const val ENABLE_MODULE = "_enable_module"
const val ENABLE_MODULE_LOG = "_enable_module_log"
const val ENABLE_HIDE_ICON = "_hide_icon"
const val ENABLE_COLOR_ICON_HOOK = "_color_icon_hook"
const val ENABLE_NOTIFY_ICON_HOOK = "_notify_icon_hook"

View File

@@ -46,6 +46,8 @@ class ConfigureActivity : BaseActivity() {
setContentView(R.layout.activity_config)
/** 返回按钮点击事件 */
findViewById<View>(R.id.title_back_icon).setOnClickListener { onBackPressed() }
/** 设置标题个数文本 */
findViewById<TextView>(R.id.config_title_count_text).text = "已适配 ${IconPackParams.iconDatas.size} 个 APP 的通知图标"
/** 设置列表元素和 Adapter */
findViewById<ListView>(R.id.config_list_view).apply {
adapter = object : BaseAdapter() {

View File

@@ -53,7 +53,7 @@ class MainActivity : BaseActivity() {
setContentView(R.layout.activity_main)
/** 设置文本 */
findViewById<TextView>(R.id.main_text_version).text = "当前版本:$moduleVersion"
findViewById<TextView>(R.id.main_text_miui_version).text = "MIUI 版本:$miuiVersion"
findViewById<TextView>(R.id.main_text_miui_version).text = "MIUI 版本:$miuiFullVersion"
when {
/** 判断是否为 MIUI 系统 */
isNotMIUI ->
@@ -64,15 +64,24 @@ class MainActivity : BaseActivity() {
confirmButton(text = "退出") { finish() }
noCancelable()
}
/** 判断最低系统版本 */
/** 判断最低 Android 系统版本 */
isLowerAndroidP ->
showDialog {
title = "系统版本过低"
title = "Android 系统版本过低"
msg = "此模块最低支持基于 Android 9 的 MIUI 系统,你的系统版本过低不再进行适配。\n" +
"如有问题请联系 酷安 @星夜不荟"
confirmButton(text = "退出") { finish() }
noCancelable()
}
/** 判断最低 MIUI 版本 */
isNotSupportMiuiVersion ->
showDialog {
title = "MIUI 版本过低"
msg = "此模块最低支持 MIUI 12 系统,你的 MIUI 版本为 ${miuiVersion},不再进行适配。\n" +
"如有问题请联系 酷安 @星夜不荟"
confirmButton(text = "退出") { finish() }
noCancelable()
}
/** 判断是否 Hook */
isHooked() -> {
findViewById<LinearLayout>(R.id.main_lin_status).setBackgroundResource(R.drawable.green_round)
@@ -91,20 +100,28 @@ class MainActivity : BaseActivity() {
}
}
/** 初始化 View */
val notifyIconConfigItem = findViewById<View>(R.id.config_item_notify)
val moduleEnableSwitch = findViewById<SwitchCompat>(R.id.module_enable_switch)
val moduleEnableLogSwitch = findViewById<SwitchCompat>(R.id.module_enable_log_switch)
val notifyIconConfigItem = findViewById<View>(R.id.config_item_notify)
val hideIconInLauncherSwitch = findViewById<SwitchCompat>(R.id.hide_icon_in_launcher_switch)
val colorIconHookSwitch = findViewById<SwitchCompat>(R.id.color_icon_fix_switch)
val notifyIconHookSwitch = findViewById<SwitchCompat>(R.id.notify_icon_fix_switch)
/** 获取 Sp 存储的信息 */
notifyIconConfigItem.isVisible = getBoolean(HookMedium.ENABLE_COLOR_ICON_HOOK, default = true)
moduleEnableLogSwitch.isVisible = getBoolean(HookMedium.ENABLE_MODULE, default = true)
moduleEnableSwitch.isChecked = getBoolean(HookMedium.ENABLE_MODULE, default = true)
moduleEnableLogSwitch.isChecked = getBoolean(HookMedium.ENABLE_MODULE_LOG, default = false)
hideIconInLauncherSwitch.isChecked = getBoolean(HookMedium.ENABLE_HIDE_ICON)
colorIconHookSwitch.isChecked = getBoolean(HookMedium.ENABLE_COLOR_ICON_HOOK, default = true)
notifyIconHookSwitch.isChecked = getBoolean(HookMedium.ENABLE_NOTIFY_ICON_HOOK, default = true)
moduleEnableSwitch.setOnCheckedChangeListener { btn, b ->
if (!btn.isPressed) return@setOnCheckedChangeListener
putBoolean(HookMedium.ENABLE_MODULE, b)
moduleEnableLogSwitch.isVisible = b
}
moduleEnableLogSwitch.setOnCheckedChangeListener { btn, b ->
if (!btn.isPressed) return@setOnCheckedChangeListener
putBoolean(HookMedium.ENABLE_MODULE_LOG, b)
}
hideIconInLauncherSwitch.setOnCheckedChangeListener { btn, b ->
if (!btn.isPressed) return@setOnCheckedChangeListener

View File

@@ -91,6 +91,24 @@ val isMIUI by lazy {
*/
inline val isNotMIUI get() = !isMIUI
/**
* 是否为支持的 MIUI 版本
* @return [Boolean]
*/
val isSupportMiuiVersion
get() = when (miuiVersion) {
"12" -> true
"12.5" -> true
"13" -> true
else -> false
}
/**
* 是否不为支持的 MIUI 版本
* @return [Boolean]
*/
inline val isNotSupportMiuiVersion get() = !isSupportMiuiVersion
/**
* 获取 MIUI 版本
* @return [String]
@@ -109,7 +127,15 @@ val miuiVersion
"V13" -> "13"
else -> it.replace(oldValue = "V", newValue = "")
}
} + " " + findPropString(key = "ro.system.build.version.incremental")
}.trim()
else "NULL"
/**
* 获取 MIUI 完全版本
* @return [String]
*/
val miuiFullVersion
get() = if (isMIUI) (miuiVersion + " " + findPropString(key = "ro.system.build.version.incremental"))
else "不是 MIUI 系统"
/**

View File

@@ -25,7 +25,15 @@ import de.robv.android.xposed.XSharedPreferences
object XPrefUtils {
fun getBoolean(key: String, default: Boolean = false) = pref.getBoolean(key, default)
private var xPrefCacheKeyValueBooleans = HashMap<String, Boolean>()
fun getBoolean(key: String, default: Boolean = false) =
xPrefCacheKeyValueBooleans[key].let {
it ?: pref.getBoolean(key, default).let { e ->
xPrefCacheKeyValueBooleans[key] = e
e
}
}
private val pref: XSharedPreferences
get() {

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#777777">
<item>
<shape android:shape="rectangle">
<solid android:color="#66DAD9D9" />
<corners android:radius="15dp" />
</shape>
</item>
</ripple>

View File

@@ -28,15 +28,32 @@
android:src="@mipmap/back"
android:tint="@color/colorTextGray" />
<TextView
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center|start"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:singleLine="true"
android:text="通知图标优化名单"
android:textColor="@color/colorTextGray"
android:textSize="25sp"
android:textSize="19sp"
android:textStyle="bold" />
<TextView
android:id="@+id/config_title_count_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="..."
android:textColor="@color/colorTextDark"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout

View File

@@ -150,6 +150,7 @@
android:layout_marginLeft="15dp"
android:layout_marginTop="10dp"
android:layout_marginRight="15dp"
android:animateLayoutChanges="true"
android:background="@drawable/permotion_round"
android:elevation="0dp"
android:gravity="center"
@@ -160,18 +161,28 @@
<com.fankes.miui.notify.view.MaterialSwitch
android:id="@+id/module_enable_switch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="40dp"
android:layout_marginTop="5dp"
android:text="启用模块"
android:textColor="@color/colorTextGray"
android:textSize="15sp" />
<com.fankes.miui.notify.view.MaterialSwitch
android:id="@+id/module_enable_log_switch"
android:layout_width="match_parent"
android:layout_height="35dp"
android:layout_marginBottom="5dp"
android:text="启用调试日志"
android:textColor="@color/colorTextGray"
android:textSize="15sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:alpha="0.6"
android:lineSpacingExtra="6dp"
android:text="关闭后模块将彻底停止工作,以下选项都将不再生效。"
android:text="模块关闭后功能都将彻底停止工作,以下选项都将不再生效。"
android:textColor="@color/colorTextDark"
android:textSize="12sp" />
</LinearLayout>
@@ -352,7 +363,7 @@
android:layout_marginBottom="10dp"
android:alpha="0.8"
android:lineSpacingExtra="6dp"
android:text="Q.哪些是已知问题?\nA.MIUI 自己的系统应用的通知图标仍然可能出现黑白块的情况,可使用通知图标优化暂时修复其图标问题,后期只能等官方修复(基本上没什么可能性)。动态小图标可能会在高版本系统中闪烁,这是 MIUI 的问题,后期仍在想解决办法。"
android:text="Q.哪些是已知问题?\nA.以下是问题描述列表:\n(1) MIUI 自己的系统应用的通知图标仍然可能出现黑白块的情况,可使用通知图标优化暂时修复其图标问题,后期只能等官方修复(基本上没什么可能性)。\n(2) 动态小图标可能会在高版本系统中闪烁,这是 MIUI 的问题,后期仍在想解决办法。\n(3) 使用 Zygisk 方式运行的 Lsposed 可能会发生通知优化图标 Hook 不生效的问题(出现黑白块),仅在最新版本的 MIUI 13 开发内测版中遇到,若出现问题请使用 Ramdisk 版本的 Lsposed。"
android:textColor="@color/colorTextDark"
android:textSize="12sp" />