mirror of
https://github.com/fankes/MIUINativeNotifyIcon.git
synced 2025-09-07 11:09:52 +08:00
Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
7a4e254230 | |||
0534ab9218 | |||
5cee229a99 | |||
b6920e3ca1 | |||
|
a4f7c95f84 | ||
38803846cd |
3
.github/ISSUE_TEMPLATE/----------.md
vendored
3
.github/ISSUE_TEMPLATE/----------.md
vendored
@@ -23,6 +23,7 @@ assignees: ''
|
|||||||
|
|
||||||
* (若直接在附件提交这里可不填)
|
* (若直接在附件提交这里可不填)
|
||||||
|
|
||||||
<!--- 提交时请将示例内容全部删除 --->
|
<!--- 提交时请将括号内容包括括号全部删除,填入你自己的内容 --->
|
||||||
|
<!--- 请保留模板原始标题 --->
|
||||||
<!--- 不按规定提交的 issues 将直接被关闭 --->
|
<!--- 不按规定提交的 issues 将直接被关闭 --->
|
||||||
<!--- Create by Template --->
|
<!--- Create by Template --->
|
||||||
|
3
.github/ISSUE_TEMPLATE/----bug---.md
vendored
3
.github/ISSUE_TEMPLATE/----bug---.md
vendored
@@ -46,6 +46,7 @@ assignees: fankes
|
|||||||
|
|
||||||
</code></pre></details>
|
</code></pre></details>
|
||||||
|
|
||||||
<!--- 提交时请将示例内容全部删除 --->
|
<!--- 提交时请将括号内容包括括号全部删除,填入你自己的内容 --->
|
||||||
|
<!--- 请保留模板原始标题 --->
|
||||||
<!--- 不按规定提交的 issues 将直接被关闭 --->
|
<!--- 不按规定提交的 issues 将直接被关闭 --->
|
||||||
<!--- Create by Template --->
|
<!--- Create by Template --->
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
<img src="https://github.com/fankes/MIUINativeNotifyIcon/blob/master/app/src/main/ic_launcher-playstore.png" width = "100" height = "100"/>
|
<img src="https://github.com/fankes/MIUINativeNotifyIcon/blob/master/app/src/main/ic_launcher-playstore.png" width = "100" height = "100"/>
|
||||||
<br/>
|
<br/>
|
||||||
@@ -12,7 +12,7 @@ Fix the native notification bar icon function abandoned by the MIUI development
|
|||||||
# 开始使用
|
# 开始使用
|
||||||
|
|
||||||
点击下载最新版本
|
点击下载最新版本
|
||||||
<a href='https://github.com/fankes/MIUINativeNotifyIcon/releases'></a>
|
<a href='https://github.com/fankes/MIUINativeNotifyIcon/releases'></a>
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
⚠️ 适配说明<br/>
|
⚠️ 适配说明<br/>
|
||||||
|
|
||||||
|
@@ -51,9 +51,13 @@ android {
|
|||||||
tasks.whenTaskAdded {
|
tasks.whenTaskAdded {
|
||||||
task -> if (task.name == "lintVitalRelease") task.enabled = false
|
task -> if (task.name == "lintVitalRelease") task.enabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 移除无效耗时 lint Task */
|
||||||
tasks.whenTaskAdded {
|
tasks.whenTaskAdded {
|
||||||
task -> if (task.name == "lintVitalAnalyzeRelease") task.enabled = false
|
task -> if (task.name == "lintVitalAnalyzeRelease") task.enabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 移除无效耗时 lint Task */
|
||||||
tasks.whenTaskAdded {
|
tasks.whenTaskAdded {
|
||||||
task -> if (task.name == "lintVitalReportRelease") task.enabled = false
|
task -> if (task.name == "lintVitalReportRelease") task.enabled = false
|
||||||
}
|
}
|
||||||
|
@@ -51,7 +51,6 @@ import com.highcapable.yukihookapi.hook.log.loggerD
|
|||||||
import com.highcapable.yukihookapi.hook.log.loggerW
|
import com.highcapable.yukihookapi.hook.log.loggerW
|
||||||
import com.highcapable.yukihookapi.hook.param.PackageParam
|
import com.highcapable.yukihookapi.hook.param.PackageParam
|
||||||
import com.highcapable.yukihookapi.hook.type.android.ContextClass
|
import com.highcapable.yukihookapi.hook.type.android.ContextClass
|
||||||
import com.highcapable.yukihookapi.hook.type.android.DrawableClass
|
|
||||||
import com.highcapable.yukihookapi.hook.type.android.ImageViewClass
|
import com.highcapable.yukihookapi.hook.type.android.ImageViewClass
|
||||||
import com.highcapable.yukihookapi.hook.type.java.IntType
|
import com.highcapable.yukihookapi.hook.type.java.IntType
|
||||||
import com.highcapable.yukihookapi.hook.xposed.proxy.YukiHookXposedInitProxy
|
import com.highcapable.yukihookapi.hook.xposed.proxy.YukiHookXposedInitProxy
|
||||||
@@ -76,9 +75,6 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
private const val NotificationViewWrapperClass =
|
private const val NotificationViewWrapperClass =
|
||||||
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationViewWrapper"
|
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationViewWrapper"
|
||||||
|
|
||||||
/** 原生存在的类 */
|
|
||||||
private const val ContrastColorUtilClass = "com.android.internal.util.ContrastColorUtil"
|
|
||||||
|
|
||||||
/** 未确定是否只有旧版本存在的类 */
|
/** 未确定是否只有旧版本存在的类 */
|
||||||
private const val ExpandableNotificationRowClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.ExpandableNotificationRow"
|
private const val ExpandableNotificationRowClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.ExpandableNotificationRow"
|
||||||
|
|
||||||
@@ -98,30 +94,11 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
/**
|
/**
|
||||||
* - 这个是修复彩色图标的关键核心代码判断
|
* - 这个是修复彩色图标的关键核心代码判断
|
||||||
*
|
*
|
||||||
* 判断是否为灰度图标 - 反射执行系统方法
|
* 判断是否为灰度图标 - [isXmsf] 直接标记为非灰度图标防止 💩 MIUI 乱改
|
||||||
* @param context 实例
|
|
||||||
* @param drawable 要判断的图标
|
* @param drawable 要判断的图标
|
||||||
* @return [Boolean]
|
* @return [Boolean]
|
||||||
*/
|
*/
|
||||||
private fun PackageParam.isGrayscaleIcon(context: Context, drawable: Drawable) = safeOfFalse {
|
private fun StatusBarNotification.isGrayscaleIcon(drawable: Drawable) = !isXmsf && BitmapCompatTool.isGrayscaleDrawable(drawable)
|
||||||
ContrastColorUtilClass.clazz.let {
|
|
||||||
it.method {
|
|
||||||
name = "isGrayscaleIcon"
|
|
||||||
param(DrawableClass)
|
|
||||||
}.get(it.method {
|
|
||||||
name = "getInstance"
|
|
||||||
param(ContextClass)
|
|
||||||
}.get().invoke(context)).invoke<Boolean>(drawable) ?: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前通知栏的样式
|
|
||||||
* @return [Boolean]
|
|
||||||
*/
|
|
||||||
private fun PackageParam.isShowMiuiStyle() = safeOfFalse {
|
|
||||||
NotificationUtilClass.clazz.method { name = "showMiuiStyle" }.get().invoke() ?: false
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否为新版本 MIUI 方案
|
* 是否为新版本 MIUI 方案
|
||||||
@@ -129,8 +106,15 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
* 拥有状态栏图标颜色检查功能
|
* 拥有状态栏图标颜色检查功能
|
||||||
* @return [Boolean]
|
* @return [Boolean]
|
||||||
*/
|
*/
|
||||||
private fun PackageParam.hasIgnoreStatusBarIconColor() = safeOfFalse {
|
private val PackageParam.hasIgnoreStatusBarIconColor
|
||||||
NotificationUtilClass.clazz.hasMethod(name = "ignoreStatusBarIconColor", ExpandedNotificationClass.clazz)
|
get() = NotificationUtilClass.clazz.hasMethod(name = "ignoreStatusBarIconColor", ExpandedNotificationClass.clazz)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前通知栏的样式
|
||||||
|
* @return [Boolean]
|
||||||
|
*/
|
||||||
|
private fun PackageParam.isShowMiuiStyle() = safeOfFalse {
|
||||||
|
NotificationUtilClass.clazz.method { name = "showMiuiStyle" }.get().invoke() ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -222,10 +206,11 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
if (iconDrawable == null) return@safeRun
|
if (iconDrawable == null) return@safeRun
|
||||||
/** 如果没开启修复 APP 的彩色图标 */
|
/** 如果没开启修复 APP 的彩色图标 */
|
||||||
if (!prefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)) return@safeRun
|
if (!prefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)) return@safeRun
|
||||||
/** 判断是否不是灰度图标 */
|
|
||||||
val isNotGrayscaleIcon = !isGrayscaleIcon(context, iconDrawable)
|
|
||||||
/** 获取通知对象 - 由于 MIUI 的版本迭代不规范性可能是空的 */
|
/** 获取通知对象 - 由于 MIUI 的版本迭代不规范性可能是空的 */
|
||||||
expandedNf?.also { notifyInstance ->
|
expandedNf?.also { notifyInstance ->
|
||||||
|
/** 判断是否不是灰度图标 */
|
||||||
|
val isNotGrayscaleIcon = !notifyInstance.isGrayscaleIcon(iconDrawable)
|
||||||
|
|
||||||
/** 目标彩色通知 APP 图标 */
|
/** 目标彩色通知 APP 图标 */
|
||||||
var customIcon: Bitmap? = null
|
var customIcon: Bitmap? = null
|
||||||
if (prefs.getBoolean(ENABLE_NOTIFY_ICON_FIX, default = true))
|
if (prefs.getBoolean(ENABLE_NOTIFY_ICON_FIX, default = true))
|
||||||
@@ -243,12 +228,12 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
}
|
}
|
||||||
/** 打印日志 */
|
/** 打印日志 */
|
||||||
if (prefs.getBoolean(ENABLE_MODULE_LOG))
|
if (prefs.getBoolean(ENABLE_MODULE_LOG))
|
||||||
loggerD(msg = "hook Icon [${findAppName(notifyInstance)}][${notifyInstance.opPkgName}] custom [${customIcon != null}] grayscale [${!isNotGrayscaleIcon}]")
|
loggerD(msg = "Icon --> [${findAppName(notifyInstance)}][${notifyInstance.opPkgName}] custom [${customIcon != null}] grayscale [${!isNotGrayscaleIcon}] xmsf [${notifyInstance.isXmsf}]")
|
||||||
when {
|
when {
|
||||||
/** 处理自定义通知图标优化 */
|
/** 处理自定义通知图标优化 */
|
||||||
customIcon != null -> it(customIcon!!)
|
customIcon != null -> it(customIcon!!)
|
||||||
/** 若不是灰度图标自动处理为圆角 */
|
/** 若不是灰度图标自动处理为圆角 */
|
||||||
isNotGrayscaleIcon -> it(expandedNf.compatNotifyIcon(context, iconDrawable).toBitmap().round(15.dp(context)))
|
isNotGrayscaleIcon -> it(notifyInstance.compatNotifyIcon(context, iconDrawable).toBitmap().round(15.dp(context)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -295,7 +280,7 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
val iconDrawable = notifyInstance.notification.smallIcon.loadDrawable(context)
|
val iconDrawable = notifyInstance.notification.smallIcon.loadDrawable(context)
|
||||||
|
|
||||||
/** 判断图标风格 */
|
/** 判断图标风格 */
|
||||||
val isGrayscaleIcon = isGrayscaleIcon(context, iconDrawable)
|
val isGrayscaleIcon = notifyInstance.isGrayscaleIcon(iconDrawable)
|
||||||
|
|
||||||
/** 自定义默认小图标 */
|
/** 自定义默认小图标 */
|
||||||
var customIcon: Bitmap? = null
|
var customIcon: Bitmap? = null
|
||||||
@@ -340,7 +325,7 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
background = DrawableBuilder().rounded().solidColor(iconColor).build()
|
background = DrawableBuilder().rounded().solidColor(iconColor).build()
|
||||||
} else iconImageView.apply {
|
} else iconImageView.apply {
|
||||||
/** 重新设置图标 */
|
/** 重新设置图标 */
|
||||||
setImageDrawable(expandedNf.compatNotifyIcon(context, iconDrawable))
|
setImageDrawable(notifyInstance.compatNotifyIcon(context, iconDrawable))
|
||||||
/** 设置裁切到边界 */
|
/** 设置裁切到边界 */
|
||||||
clipToOutline = true
|
clipToOutline = true
|
||||||
/** 设置一个圆角轮廓裁切 */
|
/** 设置一个圆角轮廓裁切 */
|
||||||
@@ -378,7 +363,7 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
notifyInstance.notification.smallIcon.loadDrawable(context)
|
notifyInstance.notification.smallIcon.loadDrawable(context)
|
||||||
|
|
||||||
/** 判断是否不是灰度图标 */
|
/** 判断是否不是灰度图标 */
|
||||||
val isNotGrayscaleIcon = !isGrayscaleIcon(context, iconDrawable)
|
val isNotGrayscaleIcon = !notifyInstance.isGrayscaleIcon(iconDrawable)
|
||||||
|
|
||||||
/** 获取目标修复彩色图标的 APP */
|
/** 获取目标修复彩色图标的 APP */
|
||||||
var isTargetFixApp = false
|
var isTargetFixApp = false
|
||||||
@@ -431,9 +416,9 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
* 因为之前的 MIUI 版本的状态栏图标颜色会全部设置为白色的 - 找不到修复的地方就直接判断版本了
|
* 因为之前的 MIUI 版本的状态栏图标颜色会全部设置为白色的 - 找不到修复的地方就直接判断版本了
|
||||||
* 对于之前没有通知图标色彩判断功能的版本判断是 MIUI 样式就停止 Hook
|
* 对于之前没有通知图标色彩判断功能的版本判断是 MIUI 样式就停止 Hook
|
||||||
*/
|
*/
|
||||||
replaceAny { if (hasIgnoreStatusBarIconColor()) false else isShowMiuiStyle() }
|
replaceAny { if (hasIgnoreStatusBarIconColor) false else isShowMiuiStyle() }
|
||||||
}
|
}
|
||||||
if (hasIgnoreStatusBarIconColor())
|
if (hasIgnoreStatusBarIconColor)
|
||||||
injectMember {
|
injectMember {
|
||||||
method {
|
method {
|
||||||
name = "ignoreStatusBarIconColor"
|
name = "ignoreStatusBarIconColor"
|
||||||
@@ -464,7 +449,7 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
}
|
}
|
||||||
afterHook {
|
afterHook {
|
||||||
/** 对于之前没有通知图标色彩判断功能的版本判断是 MIUI 样式就停止 Hook */
|
/** 对于之前没有通知图标色彩判断功能的版本判断是 MIUI 样式就停止 Hook */
|
||||||
if (hasIgnoreStatusBarIconColor() || !isShowMiuiStyle())
|
if (hasIgnoreStatusBarIconColor || !isShowMiuiStyle())
|
||||||
(globalContext ?: args[0] as Context).also { context ->
|
(globalContext ?: args[0] as Context).also { context ->
|
||||||
hookSmallIconOnSet(
|
hookSmallIconOnSet(
|
||||||
context = context,
|
context = context,
|
||||||
@@ -522,7 +507,7 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
method { name = "handleHeaderViews" }
|
method { name = "handleHeaderViews" }
|
||||||
afterHook {
|
afterHook {
|
||||||
/** 对于之前没有通知图标色彩判断功能的版本判断是 MIUI 样式就停止 Hook */
|
/** 对于之前没有通知图标色彩判断功能的版本判断是 MIUI 样式就停止 Hook */
|
||||||
if (!hasIgnoreStatusBarIconColor() && isShowMiuiStyle()) return@afterHook
|
if (!hasIgnoreStatusBarIconColor && isShowMiuiStyle()) return@afterHook
|
||||||
|
|
||||||
/** 获取小图标 */
|
/** 获取小图标 */
|
||||||
val iconImageView =
|
val iconImageView =
|
||||||
|
@@ -3438,6 +3438,57 @@ object IconPackParams {
|
|||||||
iconColor = 0xff4679e9.toInt(),
|
iconColor = 0xff4679e9.toInt(),
|
||||||
contributorName = "fankes"
|
contributorName = "fankes"
|
||||||
),
|
),
|
||||||
|
IconDataBean(
|
||||||
|
isEnabled = true,
|
||||||
|
isEnabledAll = false,
|
||||||
|
appName = "QQ阅读",
|
||||||
|
packageName = "com.qq.reader",
|
||||||
|
iconBitmap = ("iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAAARzQklUCAgI\n" +
|
||||||
|
"CHwIZIgAAAMRSURBVGiB7ZhNSFVBGIbfCVIuBG4UMgiSgihq5dZqY5ERSOSunRtXgYs2tW3TImjh\n" +
|
||||||
|
"tkWbqHDRIrAfI7CltErIwMJIJfuRDOEKGjwtZvTe5J6fb+7Rg+ADlwv3fjPzvjNz5nzfSHvs0RSu\n" +
|
||||||
|
"yM6AbklXJJ2RdExSh6S/kpYkTUl6I+mJc26uyHGbBugFJsnPI6CrbN0CKsB9g/B6qsBQmeLbjbOe\n" +
|
||||||
|
"xEgZ4isFiS/HBDBSoPgNru2U+O5tEA+wDHRa9eyL8HA7ok0e2iTdsjYyvQeAw5K+WgcxsCqp0zn3\n" +
|
||||||
|
"J28D6wr0G+OtVCRdtTSwGjhnjI/hrCXYauC4MT6Gk5Zgq4GDxvgYTCeR1UCLMT6GVktwzDG63eQ+\n" +
|
||||||
|
"gSS7gZ/G+Bi+W4KtBiYkrRvbWPgo6XEhPVHL8R8Ag4T8HZ/I9QJ3gZkm04c1YAwY2kgj8FluP3AH\n" +
|
||||||
|
"GA9jDMYYmGsw4Bw+/+8HKiGuG5/c/TAIfw8MA+2hj54geDohfiXGQJagKvAUGMCvSgvQh5/RRqzh\n" +
|
||||||
|
"K7Hu0P/RILrRRG1lOcbAeI6ONwfAr0xPnbgRYCUYHaG2BQeACUPfAGMxBvqNg2wwDdwEOoG28GkH\n" +
|
||||||
|
"bgCzkX32JelsmI1SKy46JN0zu68xL38rcaSJPq5LWpTU6px7mKsFfm/PACfCzJXFcNAwA4zmtkyt\n" +
|
||||||
|
"3q3i9/NCCeJngS78cwQw2Uhr0ovsV/iuSOqV9CG3++J4J+mCpANbNP1HkoH6p35/gaKs1I+d/yTC\n" +
|
||||||
|
"n+mjYeuUvYUWgpa4TBh/JJbFcJa+xKIenyp8knQoynlxzEs6lVTop95KAFX5B7lM1p1zidsnK51e\n" +
|
||||||
|
"KFhMDKn1QZaB3wUKieVb2p+7YQVSS8wsA0sFCokldRKzDCwWKCSWhm/gDXaDgVQNWQY+Fygkli9p\n" +
|
||||||
|
"f2beTuOrrMuSLkk6XZCoLKYkvZL0wjn3Oi0w5nr9vKQ+SRdVyxSbZVXSS0nPJD13zqUenYWAL+QH\n" +
|
||||||
|
"8IX6SnI6k8gK/spm84ajNOrMjOKLoCSqIWagdNFJ4Iv4QeBtnfCJ8Ftb2fpMBDO7S/RO8w+xh352\n" +
|
||||||
|
"EqfboQAAAABJRU5ErkJggg==").bitmap,
|
||||||
|
iconColor = 0xff45afff.toInt(),
|
||||||
|
contributorName = "fankes"
|
||||||
|
),
|
||||||
|
IconDataBean(
|
||||||
|
isEnabled = true,
|
||||||
|
isEnabledAll = false,
|
||||||
|
appName = "QQ浏览器",
|
||||||
|
packageName = "com.tencent.mtt",
|
||||||
|
iconBitmap = ("iVBORw0KGgoAAAANSUhEUgAAADUAAAAyCAYAAAD845PIAAAAAXNSR0IArs4c6QAAAARzQklUCAgI\n" +
|
||||||
|
"CHwIZIgAAAPhSURBVGiB5ZpLiB1FFIb/I4nR8REw0UkGE9zERyIDxriIbgYXQTKuXKhBERcujAYf\n" +
|
||||||
|
"oAshiwEloLgQNA+UoKCiC40YRBEXCYoIEiE4YzJxQPJkzEtEGXQw8LmovtjpdPf0qep7r+gPDUPX\n" +
|
||||||
|
"qXPOV9W3q+r0SP9BWTecAssl5a/fJB3PrmNmdrobcVsVsBzYCHxCM50CtgKjwEC/8z9PwDpgd0OQ\n" +
|
||||||
|
"OsDtwM39hlkLvJMIU9QM8CLh0e050JaWYYqaBh7tFcwA8H6XgfLa3m2gNT2EyeuzbgEN9wmoo21t\n" +
|
||||||
|
"Ay0FzvYZCtr6jQHzga/6TZPTA21APd9vioKmafi6v6gCaIWkx5NHRpqV9J2koy34WqKUnIBXEkZ0\n" +
|
||||||
|
"J/AwcGvB5yBhB/IMcDzS9wwxOw9gNXAuMug9DWMMArsiY/jXL+C5iEDfAAsiYq2LiHUWuMwbaI8z\n" +
|
||||||
|
"yF9emEK8FRFg99b5PO9FASyTNOLMa5MXJC8zm5L0tLPbaGNL4DHniO1wJlMX+wtH3DN1voqv9Ouc\n" +
|
||||||
|
"ubS56fzYYbsIuLqqsQh1pcPxjKQfHPZzadJpv6yqIQXqgJmdcyZSp/1O+2urGopQCx1O25wlmdkZ\n" +
|
||||||
|
"+XYejaHmOZxOO2y74bNyAopQPzucLnXYNtUqh+2JqoYUqCGH7ZwCrpJ0uaNLJVTxcfNM/wiwwMxm\n" +
|
||||||
|
"HX0ELFFYOi6RJDPbmzXdqFDsrPytFFQJVQx4v3Pxva+Bz4XAZmAf8EuJj6PAy8BdwLzMdrZB7Cua\n" +
|
||||||
|
"Qo04ob4GKh8ZYBMw6fC3M+t3C3Cyxm6iEVAukXEnWOmuAnjX6aej01n/0RqbMS/UxohExgo+tkbh\n" +
|
||||||
|
"/KMvMz9PVLSv9EINEndIHMv6vxBLUtBLmb/rgQ3ANuBXGjx6F9QozOykpLdcIxE0AAyqndqGJD0L\n" +
|
||||||
|
"HJH0mqTbJX0kaY2kD6K8AesjRvY24JGWZqlKrxLOfHHKHDTVt1mf1M86TbQPuDQF7OAcASaAp4DF\n" +
|
||||||
|
"hM8wvdIbKVAraxxPZO3rqV9TuqUNVXmXFjM7MrMDkp4saZqV9JDCNut1SddEj1y87kzqzYU7jS3Z\n" +
|
||||||
|
"/bf7MEMd/ZQ8LIRPOp3y2U3E1ezaVunxp/bxy8vMvpf0oKRdZnZQ0nDySKXrhrKbjaEkycxOKIBJ\n" +
|
||||||
|
"0h2pGbWgQ2U3XVCSZGZ/ZH+eSkonXXvNrPT854bKaTyhbxvaXdWQAlU69T3Spwp7wvYF7Pg3vfXa\n" +
|
||||||
|
"BPuwhzAzwNquAuXA7gamSpL4E3gT+HyOZPcQzkx1h8v3mubT2r/GEWoVw9k1X9IxSfvN7HDWfrHC\n" +
|
||||||
|
"Z6IhhZrh7wrVq3Ez+zHnZ7XC+jOkUK+flDSVLSf/X/0N9IzKpFVJbfwAAAAASUVORK5CYII=").bitmap,
|
||||||
|
iconColor = 0xff6593f1.toInt(),
|
||||||
|
contributorName = "fankes"
|
||||||
|
),
|
||||||
// TODO 可继续在这里添加更多 APP
|
// TODO 可继续在这里添加更多 APP
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* MIUINativeNotifyIcon - Fix the native notification bar icon function abandoned by the MIUI development team.
|
||||||
|
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
|
||||||
|
* https://github.com/fankes/MIUINativeNotifyIcon
|
||||||
|
*
|
||||||
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
|
* as published by the Free Software Foundation; either
|
||||||
|
* version 3 of the License, or any later version and our eula as published
|
||||||
|
* by ferredoxin.
|
||||||
|
*
|
||||||
|
* This software 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
|
||||||
|
* Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* and eula along with this software. If not, see
|
||||||
|
* <https://www.gnu.org/licenses/>
|
||||||
|
*
|
||||||
|
* This file is Created by fankes on 2022/2/19.
|
||||||
|
*/
|
||||||
|
package com.fankes.miui.notify.utils
|
||||||
|
|
||||||
|
import android.graphics.*
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.util.ArrayMap
|
||||||
|
import androidx.core.graphics.drawable.toBitmap
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 这是一个从 AOSP 源码中分离出来的功能
|
||||||
|
*
|
||||||
|
* 主要作用于兼容部分 MIUI 魔改颜色判断代码造成判断位图灰度功能失效
|
||||||
|
*/
|
||||||
|
object BitmapCompatTool {
|
||||||
|
|
||||||
|
/** 缓存已判断的结果防止卡顿 */
|
||||||
|
private var cachedBitmapGrayscales = ArrayMap<Int, Boolean>()
|
||||||
|
|
||||||
|
private var tempBuffer = intArrayOf(0)
|
||||||
|
private var tempCompactBitmap: Bitmap? = null
|
||||||
|
private var tempCompactBitmapCanvas: Canvas? = null
|
||||||
|
private var tempCompactBitmapPaint: Paint? = null
|
||||||
|
private val tempMatrix = Matrix()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断 [Drawable] 是否为灰度位图
|
||||||
|
* @param drawable 要判断的 [Drawable]
|
||||||
|
* @return [Boolean] 是否灰度
|
||||||
|
*/
|
||||||
|
fun isGrayscaleDrawable(drawable: Drawable) = safeOfFalse { isGrayscale(drawable.toBitmap()) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断 [Bitmap] 是否为灰度位图
|
||||||
|
* @param bitmap 要判断的位图
|
||||||
|
* @return [Boolean] 是否灰度
|
||||||
|
*/
|
||||||
|
private fun isGrayscale(bitmap: Bitmap) =
|
||||||
|
cachedBitmapGrayscales[bitmap.generationId] ?: let {
|
||||||
|
var height = bitmap.height
|
||||||
|
var width = bitmap.width
|
||||||
|
if (height > 64 || width > 64) {
|
||||||
|
if (tempCompactBitmap == null) {
|
||||||
|
tempCompactBitmap = Bitmap.createBitmap(64, 64, Bitmap.Config.ARGB_8888)
|
||||||
|
.also { tempCompactBitmapCanvas = Canvas(it) }
|
||||||
|
tempCompactBitmapPaint = Paint(Paint.FILTER_BITMAP_FLAG).apply { isFilterBitmap = true }
|
||||||
|
}
|
||||||
|
tempMatrix.reset()
|
||||||
|
tempMatrix.setScale(64f / width, 64f / height, 0f, 0f)
|
||||||
|
tempCompactBitmapCanvas?.drawColor(0, PorterDuff.Mode.SRC)
|
||||||
|
tempCompactBitmapCanvas?.drawBitmap(bitmap, tempMatrix, tempCompactBitmapPaint)
|
||||||
|
height = 64
|
||||||
|
width = 64
|
||||||
|
}
|
||||||
|
val size = height * width
|
||||||
|
ensureBufferSize(size)
|
||||||
|
tempCompactBitmap?.getPixels(tempBuffer, 0, width, 0, 0, width, height)
|
||||||
|
for (i in 0 until size)
|
||||||
|
if (!isGrayscale(tempBuffer[i])) {
|
||||||
|
cachedBitmapGrayscales[bitmap.generationId] = false
|
||||||
|
return@let false
|
||||||
|
}
|
||||||
|
cachedBitmapGrayscales[bitmap.generationId] = true
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提纯 [Bitmap] 颜色判断灰度
|
||||||
|
* @param color 颜色
|
||||||
|
* @return [Boolean] 是否灰度
|
||||||
|
*/
|
||||||
|
private fun isGrayscale(color: Int): Boolean {
|
||||||
|
if (color shr 24 and 255 < 50) return true
|
||||||
|
val r = color shr 16 and 255
|
||||||
|
val g = color shr 8 and 255
|
||||||
|
val b = color and 255
|
||||||
|
return !(abs(r - g) >= 20 || abs(r - b) >= 20 || abs(g - b) >= 20)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算字节数组
|
||||||
|
* @param size 大小
|
||||||
|
*/
|
||||||
|
private fun ensureBufferSize(size: Int) {
|
||||||
|
if (tempBuffer.size < size) tempBuffer = IntArray(size)
|
||||||
|
}
|
||||||
|
}
|
@@ -5,8 +5,8 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
appVersionName = "1.65"
|
appVersionName = "1.66"
|
||||||
appVersionCode = 12
|
appVersionCode = 13
|
||||||
}
|
}
|
||||||
|
|
||||||
task clean(type: Delete) {
|
task clean(type: Delete) {
|
||||||
|
Reference in New Issue
Block a user