26 Commits
2.2 ... 2.5

Author SHA1 Message Date
25399cd88b Update version to 2.5 2022-04-14 03:11:17 +08:00
18691d8b8d 更换通知刷新方案,彻底解决系统界面卡死问题 2022-04-14 02:55:43 +08:00
7c61b09054 Update YukiHookAPI 2022-04-13 04:59:35 +08:00
7a7e179a2b Merge code 2022-04-11 23:07:37 +08:00
dbd7dbf172 Update YukiHookAPI 2022-04-10 03:13:04 +08:00
502e5dc04b Update YukiHookAPI 2022-04-09 02:32:13 +08:00
ff0c57319a Update README.md 2022-04-09 01:50:24 +08:00
647a39c327 Update README.md 2022-04-05 22:45:32 +08:00
04e8d43356 加入新安装应用的通知图标优化适配通知忽略 DEBUG 版本的 APP 2022-04-05 21:56:37 +08:00
f85d2db36e Update YukiHookAPI 2022-04-04 22:55:09 +08:00
2e5284ebe9 Update version to 2.35 2022-04-04 13:55:10 +08:00
abffc4d853 Update version to 2.35 2022-04-04 13:54:42 +08:00
5d81b8ff87 尝试修复 MIUI 12 的问题 2022-04-04 13:48:54 +08:00
d91d2736e6 修复图标缓存过大造成系统界面停止运行的问题 2022-04-04 13:38:38 +08:00
72169989f2 Merge code 2022-04-04 12:04:12 +08:00
c85da002f5 Update YukiHookAPI 2022-04-04 03:13:19 +08:00
c09a1b5760 Update README.md 2022-03-30 20:56:52 +08:00
c30e56c5aa Update YukiHookAPI 2022-03-30 14:13:48 +08:00
822e988c16 Update version to 2.3 2022-03-29 23:50:37 +08:00
fc728a75a4 Update version to 2.3 2022-03-29 23:50:09 +08:00
256e2ebfce 优化 Android 12 风格通知图标深色模式的颜色 2022-03-29 23:47:21 +08:00
be4b952f62 修复折叠情况下的经典通知图标无变化问题,添加安卓 12 以下系统经典通知情况下图标颜色实时跟随壁纸功能 2022-03-29 23:14:57 +08:00
c7263c6d94 Fix a receiver bug 2022-03-29 21:46:20 +08:00
4733578912 Update YukiHookAPI 2022-03-29 21:05:49 +08:00
87879301f0 Update YukiHookAPI 2022-03-29 21:04:03 +08:00
c9be72e5f7 Update version to 2.2 2022-03-28 14:16:58 +08:00
12 changed files with 288 additions and 165 deletions

View File

@@ -2,52 +2,61 @@
[![Blank](https://img.shields.io/badge/build-passing-brightgreen)](https://github.com/fankes/MIUINativeNotifyIcon)
[![Blank](https://img.shields.io/badge/license-AGPL3.0-blue)](https://github.com/fankes/MIUINativeNotifyIcon/blob/master/LICENSE)
[![Blank](https://img.shields.io/badge/version-v2.2-green)](https://github.com/fankes/MIUINativeNotifyIcon/releases)
[![Blank](https://img.shields.io/badge/version-v2.5-green)](https://github.com/fankes/MIUINativeNotifyIcon/releases)
[![Blank](https://img.shields.io/github/downloads/fankes/MIUINativeNotifyIcon/total?label=Release)](https://github.com/fankes/MIUINativeNotifyIcon/releases)
[![Blank](https://img.shields.io/github/downloads/Xposed-Modules-Repo/com.fankes.miui.notify/total?label=LSPosed%20Repo&logo=Android&style=flat&labelColor=F48FB1&logoColor=ffffff)](https://github.com/Xposed-Modules-Repo/com.fankes.miui.notify/releases)
[![Telegram](https://img.shields.io/static/v1?label=Telegram&message=交流讨论&color=0088cc)](https://t.me/XiaofangInternet)
[![Telegram](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/XiaofangInternet)
<br/><br/>
<img src="https://github.com/fankes/MIUINativeNotifyIcon/blob/master/app/src/main/ic_launcher-playstore.png" width = "100" height = "100"/>
<br/>
Fix the native notification bar icon function abandoned by the MIUI development team.<br/>
修复被 MIUI 开发组丢弃的原生通知图标,支持 MIUI 12、12.5、13 以及最新版本。
# Developer
## Developer
[酷安 @星夜不荟](http://www.coolapk.com/u/876977)
# 适配说明
## 适配说明
- 此模块仅支持 <b>LSPosed</b>(作用域“系统界面”)、<b>~~EdXposed(随时停止支持)~~</b>、不支持<b>太极、无极</b>
- 请确保你使用的是 MIUI 官方版本,任何第三方官改包发生的问题,开发者没有义务去解决和修复,请自求多福
- 目前最低支持基于 Android 9 版本的 MIUI 12 或 MIUI 12.5(最低建议)
- 建议最低从 MIUI 12.5 `2021-5-18` 开发版以后开始使用模块,之前的版本可能或多或少存在 MIUI 自身 BUG 不生效、黑白块的问题
- 请始终保持最新版本的 LSPosed旧版本可能会出现 Hook 不生效的问题,若最新版本依然不生效请在作用域中长按“系统界面”(“系统 UI”)选择重新优化
# 请勿用于非法用途
## 请勿用于非法用途
- 本模块完全开源免费,如果好用你可以打赏支持开发,但是请不要用于非法用途。
- 本模块发布地址仅有 [Xposed-Modules-Repo](https://github.com/Xposed-Modules-Repo/com.fankes.miui.notify/releases)、
[Release](https://github.com/fankes/MIUINativeNotifyIcon/releases)
及 [蓝奏云](https://fankes.lanzouy.com/b030o2e8h),从其他非正规渠道下载到的版本或对您造成任何影响均与我们无关。
# 贡献通知图标优化名单
## 贡献通知图标优化名单
此项目是 `AndroidNotifyIconAdapt` 项目的一部分,详情请参考下方。<br/>
此项目是 `AndroidNotifyIconAdapt` 项目的一部分,详情请参考下方。
- [Android 通知图标规范适配计划](https://github.com/fankes/AndroidNotifyIconAdapt)
# 历史背景
## 历史背景
这个模块诞生来源于 MIUI 的乱改和不规范,本来 MIUI 9 之后,官方给出了原生通知图标样式,后面由于用户反应通知栏经常出现黑白块。
这当然不是系统的错,而是国内 APP 和 `MIPUSH` 的通知极其不规范的通知图标设计。
但是呢,接到反馈后 MIUI 开发组选择直接忽略这个问题,在 `2021-5-18` 的开发版开始,把全部通知图标都改成了 APP 的彩色图标,使得之前拥有自有样式的原生图标也被破坏。
对于 Android 开发者来说,官方文档中的 `setSmallIcon` 不再适用于魔改后的 MIUI这将会严重破坏非常多的状态图标。
当然,国内的手机生态除了 `MIPUSH` 的营销通知就是社交软件的通知,可能大部分人都不会在意这件事情。
这个模块诞生来源于 MIUI 的乱改和不规范,本来 MIUI 9 之后,官方给出了原生通知图标样式,后面由于用户反应通知栏经常出现黑白块。<br/><br/>
这当然不是系统的错,而是国内 APP 和 `MIPUSH` 的通知极其不规范的通知图标设计。<br/><br/>
但是呢,接到反馈后 MIUI 开发组选择直接忽略这个问题,在 `2021-5-18` 的开发版开始,把全部通知图标都改成了 APP 的彩色图标,使得之前拥有自有样式的原生图标也被破坏。<br/><br/>
对于 Android 开发者来说,官方文档中的 `setSmallIcon` 不再适用于魔改后的 MIUI这将会严重破坏非常多的状态图标。<br/><br/>
当然,国内的手机生态除了 `MIPUSH` 的营销通知就是社交软件的通知,可能大部分人都不会在意这件事情。<br/><br/>
但是,这个模块就是为了修复被 MIUI 开发组忽略的图标问题才诞生的,并完美地给 MIUI 修复了黑白块图标的问题。
<br/>
# 探索历程
## 探索历程
原生 Android 的小图标和通知图标具有状态性。<br/><br/>
<img src="https://github.com/fankes/MIUINativeNotifyIcon/blob/master/images/native.jpg" height = "35"/><br/><br/>
@@ -59,9 +68,11 @@ Fix the native notification bar icon function abandoned by the MIUI development
而 MIUI 做了什么呢?<br/><br/>
<img src="https://github.com/fankes/MIUINativeNotifyIcon/blob/master/images/miui_n_1.jpg" height = "100"/><br/>
<img src="https://github.com/fankes/MIUINativeNotifyIcon/blob/master/images/miui_n_2.jpg" height = "100"/><br/><br/>
不曾记得是什么版本开始MIUI 把通知图标改成了这个鬼样子,寻找开发组提案也是无人问津,最后转念一想,自己干吧。<br/><br/>
不曾记得是什么版本开始MIUI 把通知图标改成了这个鬼样子,寻找开发组提案也是无人问津,最后转念一想,自己干吧。
由于目前大量通知图标都来自 `MIPUSH` 发出的营销通知,而 `MIPUSH` 的图标都是统一的彩色应用图标,很多应用也没有适配这一特性, 在通知栏广告满天飞的情况下MIUI
选择放弃原生通知功能,而做出这种违反原生通知规则的做法,而这些彩色图标被设置为单色调图标,也确实会发生黑白块的问题,但是同时又会破坏遵守规范的图标。<br/><br/>
选择放弃原生通知功能,而做出这种违反原生通知规则的做法,而这些彩色图标被设置为单色调图标,也确实会发生黑白块的问题,但是同时又会破坏遵守规范的图标。
真的没有办法了吗?在不断探索下,我找到了原生支持色彩判断的类。
```kotlin
@@ -74,18 +85,28 @@ com.android.internal.util.ContrastColorUtil
ContrastColorUtil.getInstance().isGrayscaleIcon(drawable)
```
问题就被解决了,顺便修了一下被 MIUI 破坏的通知图标以及优化了一下应用本身方块图标的圆角......<br/><br/>
最后,我想大声问一句 MIUI 开发组:“就这?” 就这么简单的问题为什么拖了这么长时间也没有结论,还要交给用户去修复,这真的是一种负责任的表现吗?<br/><br/>
后来一想,也是啊,被国内生态毒害的用户,怎么可能会去想到这些问题呢,最后只能是我自作多情,还对 MIUI 留有一点情怀吧。<br/><br/>
问题就被解决了,顺便修了一下被 MIUI 破坏的通知图标以及优化了一下应用本身方块图标的圆角......
最后,我想大声问一句 MIUI 开发组:“就这?” 就这么简单的问题为什么拖了这么长时间也没有结论,还要交给用户去修复,这真的是一种负责任的表现吗?
后来一想,也是啊,被国内生态毒害的用户,怎么可能会去想到这些问题呢,最后只能是我自作多情,还对 MIUI 留有一点情怀吧。
——来自一个无可奈何的 MIUI 老用户
# 后记
## 后记
近期重新适配了 MIUI 12、12.5、13 版本,每个版本的图标设置方法都不一样,而且改的乱七八糟的,我都要无语了,只能用了很多折中方案,毕竟我也没有那么大精力每个版本去修复,实在是累了。
特地的把自己能有的小米手机刷成各种 MIUI 版本去为酷友做专项适配,我也是很累了,也希望你们能够多多支持,也能让 MIUI 做得更好。
近期重新适配了 MIUI 12、12.5、13 版本,每个版本的图标设置方法都不一样,而且改的乱七八糟的,我都要无语了,只能用了很多折中方案,毕竟我也没有那么大精力每个版本去修复,实在是累了。<br/><br/>
特地的把自己能有的小米手机刷成各种 MIUI 版本去为酷友做专项适配,我也是很累了,也希望你们能够多多支持,也能让 MIUI 做得更好。<br/><br/>
MIUI 再不重写,怕是永远会变成安卓之光。雷军,金凡!!
# 许可证
## 捐赠支持
- 工作不易,无意外情况此项目将继续维护下去,提供更多可能,欢迎打赏。<br/><br/>
<img src="https://github.com/fankes/YuKiHookAPI/blob/master/img-src/wechat_code.jpg" width = "200" height = "200"/>
## 许可证
- [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.html)
@@ -106,5 +127,6 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
```
Powered by [YukiHookAPI](https://github.com/fankes/YukiHookAPI)<br/><br/>
Powered by [YukiHookAPI](https://github.com/fankes/YukiHookAPI)
版权所有 © 2019-2022 Fankes Studio(qzmmcn@163.com)

View File

@@ -1,7 +1,7 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'com.google.devtools.ksp' version '1.6.10-1.0.2'
id 'com.google.devtools.ksp' version '1.6.10-1.0.4'
}
android {
@@ -38,17 +38,17 @@ android {
buildTypes {
release {
minifyEnabled true
minifyEnabled rootProject.ext.enableR8
signingConfig signingConfigs.debug
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = '1.8'
jvmTarget = '11'
}
buildFeatures {
viewBinding true
@@ -72,8 +72,8 @@ tasks.whenTaskAdded {
dependencies {
compileOnly 'de.robv.android.xposed:api:82'
implementation 'com.highcapable.yukihookapi:api:1.0.67'
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.67'
implementation 'com.highcapable.yukihookapi:api:1.0.75'
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.75'
implementation "com.github.topjohnwu.libsu:core:3.1.2"
implementation 'androidx.annotation:annotation:1.3.0'
implementation 'com.geyifeng.immersionbar:immersionbar:3.2.0'

View File

@@ -41,7 +41,7 @@ object Const {
const val MODULE_VERSION_CODE = BuildConfig.VERSION_CODE
/** 当前模块的版本校验 */
const val MODULE_VERSION_VERIFY = "${MODULE_VERSION_NAME}_${MODULE_VERSION_CODE}_202203281323"
const val MODULE_VERSION_VERIFY = "${MODULE_VERSION_NAME}_${MODULE_VERSION_CODE}_202204140309"
/** 当前模块的版本校验标签 */
const val MODULE_VERSION_VERIFY_TAG = "module_version_verify"

View File

@@ -23,6 +23,7 @@
package com.fankes.miui.notify.hook.entity
import android.app.NotificationManager
import android.app.WallpaperManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
@@ -40,6 +41,7 @@ import android.view.ViewGroup
import android.view.ViewOutlineProvider
import android.widget.ImageView
import androidx.core.graphics.drawable.toBitmap
import androidx.core.view.children
import com.fankes.miui.notify.bean.IconDataBean
import com.fankes.miui.notify.const.Const
import com.fankes.miui.notify.data.DataConst
@@ -53,10 +55,7 @@ import com.fankes.miui.notify.utils.tool.BitmapCompatTool
import com.fankes.miui.notify.utils.tool.IconAdaptationTool
import com.highcapable.yukihookapi.hook.bean.VariousClass
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
import com.highcapable.yukihookapi.hook.factory.field
import com.highcapable.yukihookapi.hook.factory.hasField
import com.highcapable.yukihookapi.hook.factory.hasMethod
import com.highcapable.yukihookapi.hook.factory.method
import com.highcapable.yukihookapi.hook.factory.*
import com.highcapable.yukihookapi.hook.log.loggerD
import com.highcapable.yukihookapi.hook.log.loggerW
import com.highcapable.yukihookapi.hook.type.android.*
@@ -71,62 +70,76 @@ class SystemUIHooker : YukiBaseHooker() {
companion object {
/** MIUI 新版本存在的类 */
private const val SystemUIApplicationClass = "${SYSTEMUI_PACKAGE_NAME}.SystemUIApplication"
private const val SystemUIApplicationClass = "$SYSTEMUI_PACKAGE_NAME.SystemUIApplication"
/** MIUI 新版本存在的类 */
private const val NotificationHeaderViewWrapperInjectorClass =
"${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.row.wrapper.NotificationHeaderViewWrapperInjector"
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.row.wrapper.NotificationHeaderViewWrapperInjector"
/** MIUI 新版本存在的类 */
private const val MiuiNotificationViewWrapperClass =
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.row.wrapper.MiuiNotificationViewWrapper"
/** MIUI 新版本存在的类 */
private const val MiuiNotificationChildrenContainerClass =
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.stack.MiuiNotificationChildrenContainer"
/** 原生存在的类 */
private const val NotificationChildrenContainerClass =
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.stack.NotificationChildrenContainer"
/** 原生存在的类 */
private const val ContrastColorUtilClass = "com.android.internal.util.ContrastColorUtil"
/** 原生存在的类 */
private const val StatusBarIconViewClass = "${SYSTEMUI_PACKAGE_NAME}.statusbar.StatusBarIconView"
private const val StatusBarIconViewClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.StatusBarIconView"
/** 原生存在的类 */
private const val NotificationIconContainerClass = "${SYSTEMUI_PACKAGE_NAME}.statusbar.phone.NotificationIconContainer"
private const val NotificationIconContainerClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.phone.NotificationIconContainer"
/** 原生存在的类 */
private const val PluginManagerImplClass = "${SYSTEMUI_PACKAGE_NAME}.shared.plugins.PluginManagerImpl"
/** MIUI 存在的类 - 旧版本没有 */
private const val MiuiNotificationViewWrapperClass =
"${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.row.wrapper.MiuiNotificationViewWrapper"
private const val PluginManagerImplClass = "$SYSTEMUI_PACKAGE_NAME.shared.plugins.PluginManagerImpl"
/** 根据多个版本存在不同的包名相同的类 */
private val MiuiClockClass = VariousClass(
"${SYSTEMUI_PACKAGE_NAME}.statusbar.views.MiuiClock",
"${SYSTEMUI_PACKAGE_NAME}.statusbar.policy.MiuiClock"
"$SYSTEMUI_PACKAGE_NAME.statusbar.views.MiuiClock",
"$SYSTEMUI_PACKAGE_NAME.statusbar.policy.MiuiClock"
)
/** 根据多个版本存在不同的包名相同的类 */
private val StatusBarNotificationPresenterClass = VariousClass(
"$SYSTEMUI_PACKAGE_NAME.statusbar.phone.StatusBarNotificationPresenter",
"$SYSTEMUI_PACKAGE_NAME.statusbar.phone.StatusBar"
)
/** 根据多个版本存在不同的包名相同的类 */
private val ExpandableNotificationRowClass = VariousClass(
"${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.row.ExpandableNotificationRow",
"${SYSTEMUI_PACKAGE_NAME}.statusbar.ExpandableNotificationRow"
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.row.ExpandableNotificationRow",
"$SYSTEMUI_PACKAGE_NAME.statusbar.ExpandableNotificationRow"
)
/** 根据多个版本存在不同的包名相同的类 */
private val NotificationViewWrapperClass = VariousClass(
"${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.row.wrapper.NotificationViewWrapper",
"${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.NotificationViewWrapper"
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.row.wrapper.NotificationViewWrapper",
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationViewWrapper"
)
/** 根据多个版本存在不同的包名相同的类 */
private val NotificationHeaderViewWrapperClass = VariousClass(
"${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.row.wrapper.NotificationHeaderViewWrapper",
"${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.NotificationHeaderViewWrapper"
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.row.wrapper.NotificationHeaderViewWrapper",
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationHeaderViewWrapper"
)
/** 根据多个版本存在不同的包名相同的类 */
private val NotificationUtilClass = VariousClass(
"${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.NotificationUtil",
"${SYSTEMUI_PACKAGE_NAME}.miui.statusbar.notification.NotificationUtil"
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationUtil",
"$SYSTEMUI_PACKAGE_NAME.miui.statusbar.notification.NotificationUtil"
)
/** 根据多个版本存在不同的包名相同的类 */
private val ExpandedNotificationClass = VariousClass(
"${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.ExpandedNotification",
"${SYSTEMUI_PACKAGE_NAME}.miui.statusbar.ExpandedNotification"
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.ExpandedNotification",
"$SYSTEMUI_PACKAGE_NAME.miui.statusbar.ExpandedNotification"
)
}
@@ -139,14 +152,14 @@ class SystemUIHooker : YukiBaseHooker() {
/** 是否已经使用过缓存刷新功能 */
private var isUsingCachingMethod = false
/** 缓存的状态栏小图标实例 */
private var statusBarIconViews = HashSet<ImageView>()
/** 状态栏通知图标容器 */
private var notificationIconContainer: ViewGroup? = null
/** 缓存的通知小图标包装纸实例 */
private var notificationViewWrappers = HashSet<Any>()
/** 通知栏通知控制器 */
private var notificationPresenter: Any? = null
/** MIUI 样式下的缓存的通知小图标包装纸实例 */
private var miuiNotificationViewWrappers = HashSet<Any>()
/** 仅监听一次主题壁纸颜色变化 */
private var isWallpaperColorListenerSetUp = false
/** 是否已经注册广播 */
private var isRegisterReceiver = false
@@ -232,7 +245,7 @@ class SystemUIHooker : YukiBaseHooker() {
}.get(it.method {
name = "getInstance"
param(ContextClass)
}.get().invoke(context)).callBoolean(drawable)
}.get().invoke(context)).boolean(drawable)
}
} else BitmapCompatTool.isGrayscaleDrawable(drawable)
@@ -253,19 +266,10 @@ class SystemUIHooker : YukiBaseHooker() {
get() = safeOfFalse {
NotificationUtilClass.clazz.hasMethod {
name = "ignoreStatusBarIconColor"
param(ExpandedNotificationClass.clazz)
param(ExpandedNotificationClass)
}
}
/**
* 获取当前通知栏的样式
*
* - ❗新版本可能不存在这个方法
* @return [Boolean]
*/
private val isShowMiuiStyle
get() = safeOfFalse { NotificationUtilClass.clazz.method { name = "showMiuiStyle" }.get().invoke() ?: false }
/**
* 处理为圆角图标
* @return [Drawable]
@@ -351,18 +355,31 @@ class SystemUIHooker : YukiBaseHooker() {
*/
private val globalContext
get() = safeOfNull {
SystemUIApplicationClass.clazz.method { name = "getContext" }.ignoredError().get().invoke<Context>()
SystemUIApplicationClass.clazz.method { name = "getContext" }.ignoredError().get().invoke<Context?>() ?: appContext
}
/**
* 注册主题壁纸改变颜色监听
*
* - 仅限在 Android 12 以下注册
* @param view 实例
*/
private fun registerWallpaperColorChanged(view: View) = runInSafe {
if (isWallpaperColorListenerSetUp.not() && isUpperOfAndroidS.not()) view.apply {
WallpaperManager.getInstance(context).addOnColorsChangedListener({ _, _ -> refreshNotificationIcons() }, handler)
}
isWallpaperColorListenerSetUp = true
}
/** 刷新状态栏小图标 */
private fun refreshStatusBarIcons() = runInSafe {
StatusBarIconViewClass.clazz.field { name = "mNotification" }.also { result ->
statusBarIconViews.takeIf { it.isNotEmpty() }?.forEach {
notificationIconContainer?.children?.forEach {
/** 得到通知实例 */
val nf = result.of<StatusBarNotification>(it) ?: return
val nf = result.get(it).cast<StatusBarNotification>() ?: return
/** 刷新状态栏图标 */
compatStatusIcon(it.context, nf, nf.notification.smallIcon.loadDrawable(it.context)).also { pair ->
pair.first.let { e -> it.setImageDrawable(e) }
pair.first.let { e -> (it as? ImageView?)?.setImageDrawable(e) }
}
}
}
@@ -370,13 +387,11 @@ class SystemUIHooker : YukiBaseHooker() {
/** 刷新通知小图标 */
private fun refreshNotificationIcons() = runInSafe {
(if (hasHandleHeaderViews)
NotificationHeaderViewWrapperClass.clazz.method { name = "handleHeaderViews" }
else NotificationHeaderViewWrapperClass.clazz.method { name = "resolveHeaderViews" }).also { result ->
notificationViewWrappers.takeIf { it.isNotEmpty() }?.forEach { result.get(it).call() }
}
MiuiNotificationViewWrapperClass.clazz.method { name = "handleViews" }.ignoredError().also { result ->
miuiNotificationViewWrappers.takeIf { it.isNotEmpty() }?.forEach { result.get(it).call() }
notificationPresenter?.current {
method {
name = "updateNotificationsOnDensityOrFontScaleChanged"
emptyParam()
}.call()
}
}
@@ -498,7 +513,10 @@ class SystemUIHooker : YukiBaseHooker() {
setColorFilter(if (isUseAndroid12Style || customIconColor == 0) supportColor else customIconColor)
/** Android 12 设置图标外圈颜色 */
if (isUseAndroid12Style && customIconColor != 0)
background = DrawableBuilder().rounded().solidColor(customIconColor).build()
background = DrawableBuilder()
.rounded()
.solidColor(if (context.isSystemInDarkMode) customIconColor.brighter else customIconColor)
.build()
/** 设置原生的背景边距 */
if (isUseAndroid12Style) setPadding(4.dp(context), 4.dp(context), 4.dp(context), 4.dp(context))
} else {
@@ -511,8 +529,13 @@ class SystemUIHooker : YukiBaseHooker() {
/** 设置图标着色 */
setColorFilter(supportColor)
/** Android 12 设置图标外圈颜色 */
if (isUseAndroid12Style) background =
DrawableBuilder().rounded().solidColor(if (hasIconColor) iconColor else context.systemAccentColor).build()
(if (hasIconColor) iconColor else context.systemAccentColor).also {
if (isUseAndroid12Style)
background = DrawableBuilder()
.rounded()
.solidColor(if (context.isSystemInDarkMode) it.brighter else it)
.build()
}
/** 设置原生的背景边距 */
if (isUseAndroid12Style) setPadding(4.dp(context), 4.dp(context), 4.dp(context), 4.dp(context))
} else iconImageView.apply {
@@ -572,10 +595,10 @@ class SystemUIHooker : YukiBaseHooker() {
}
/**
* 从 [NotificationViewWrapperClass] 中获取 [StatusBarNotification]
* @return [Pair] - ([Boolean] 通知是否展开,[StatusBarNotification] 通知实例)
* 从 [NotificationViewWrapperClass] 中获取 [ExpandableNotificationRowClass]
* @return [Pair] - ([Boolean] 通知是否展开,[Any] 通知 Row 实例)
*/
private fun Any.getSbnPair(): Pair<Boolean, StatusBarNotification?> {
private fun Any.getRowPair(): Pair<Boolean, Any?> {
/** 通知是否展开 */
var isExpanded = false
@@ -583,16 +606,25 @@ class SystemUIHooker : YukiBaseHooker() {
* 从父类中得到 mRow 变量 - [ExpandableNotificationRowClass]
* 获取其中的得到通知方法
*/
val expandedNf = ExpandableNotificationRowClass.clazz
.method { name = "getEntry" }
.get(NotificationViewWrapperClass.clazz.field {
val row = NotificationViewWrapperClass.clazz.field {
name = "mRow"
}.get(this).self?.also {
isExpanded = ExpandableNotificationRowClass.clazz.method {
name = "isExpanded"
returnType = BooleanType
}.get(it).callBoolean()
}).call()?.let {
}.get(it).boolean()
}
return Pair(isExpanded, row)
}
/**
* 从 [ExpandableNotificationRowClass] 中获取 [StatusBarNotification]
* @return [StatusBarNotification] or null
*/
private fun Any?.getSbn() =
ExpandableNotificationRowClass.clazz
.method { name = "getEntry" }
.get(this).call()?.let {
it.javaClass.method {
name = "getSbn"
}.get(it).invoke<StatusBarNotification>()
@@ -600,8 +632,6 @@ class SystemUIHooker : YukiBaseHooker() {
.method { name = "getStatusBarNotification" }
.get(NotificationViewWrapperClass.clazz.field { name = "mRow" }.get(this).self)
.invoke<StatusBarNotification>()
return Pair(isExpanded, expandedNf)
}
/** 缓存图标数据 */
private fun cachingIconDatas() {
@@ -636,38 +666,34 @@ class SystemUIHooker : YukiBaseHooker() {
injectMember {
method {
name = "shouldSubstituteSmallIcon"
param(ExpandedNotificationClass.clazz)
param(ExpandedNotificationClass)
}
/**
* MIUI 12 在非原生样式下 MIPUSH 的图标着色异常
* 所以判断是 MIUI 样式就停止 Hook 状态栏图标
*/
replaceAny { hasIgnoreStatusBarIconColor.not() && isShowMiuiStyle }
replaceToFalse()
}
/** 强制回写系统的状态栏图标样式为原生 */
injectMember {
var isUseLegacy = false
method {
name = "getSmallIcon"
param(ExpandedNotificationClass.clazz, IntType)
param(ExpandedNotificationClass, IntType)
}.remedys {
method {
name = "getSmallIcon"
param(ExpandedNotificationClass.clazz)
param(ExpandedNotificationClass)
}
method {
name = "getSmallIcon"
param(ContextClass, ExpandedNotificationClass.clazz)
param(ContextClass, ExpandedNotificationClass)
}.onFind { isUseLegacy = true }
}
afterHook {
(globalContext ?: firstArgs())?.also { context ->
val expandedNf = args(if (isUseLegacy) 1 else 0).of<StatusBarNotification?>()
(globalContext ?: args().first().cast())?.also { context ->
val expandedNf = args(if (isUseLegacy) 1 else 0).cast<StatusBarNotification?>()
/** Hook 状态栏小图标 */
compatStatusIcon(
context = context,
expandedNf,
(result as Icon).loadDrawable(context)
result<Icon>()?.loadDrawable(context)
).also { pair -> if (pair.second) result = Icon.createWithBitmap(pair.first?.toBitmap()) }
}
}
@@ -681,7 +707,7 @@ class SystemUIHooker : YukiBaseHooker() {
afterHook {
instance<ImageView>().also {
if (hasIgnoreStatusBarIconColor(it.context, field { name = "mNotification" }
.of<StatusBarNotification>(instance))) it.apply {
.get(instance).cast<StatusBarNotification>())) it.apply {
alpha = 1f
colorFilter = null
} else it.apply {
@@ -690,7 +716,7 @@ class SystemUIHooker : YukiBaseHooker() {
* 图标在任何场景下跟随状态栏其它图标保持半透明
* MIUI 12 进行单独判断
*/
field { name = "mCurrentSetColor" }.ofInt(instance).also { color ->
field { name = "mCurrentSetColor" }.get(instance).int().also { color ->
if (hasIgnoreStatusBarIconColor) {
alpha = if (color.isWhite) 0.95f else 0.8f
setColorFilter(if (color.isWhite) color else Color.BLACK)
@@ -700,7 +726,7 @@ class SystemUIHooker : YukiBaseHooker() {
}
}
}
/** 记录实例 */
/** 注册广播 */
injectMember {
method {
name = "setNotification"
@@ -708,22 +734,33 @@ class SystemUIHooker : YukiBaseHooker() {
}.remedys {
method {
name = "setNotification"
param(ExpandedNotificationClass.clazz)
param(ExpandedNotificationClass)
}
}
afterHook {
if (firstArgs != null) instance<ImageView>().also {
if (args[0] != null) instance<ImageView>().also {
/** 注册壁纸颜色监听 */
registerWallpaperColorChanged(it)
/** 注册广播 */
registerReceiver(it.context)
statusBarIconViews.add(it)
}
}
}
}
/** 注入通知控制器实例 */
StatusBarNotificationPresenterClass.hook {
injectMember {
allConstructors()
afterHook { notificationPresenter = instance }
}
}
/** 注入状态栏通知图标容器实例 */
NotificationIconContainerClass.hook {
injectMember {
method { name = "calculateIconTranslations" }
afterHook {
/** 缓存实例 */
notificationIconContainer = instance<ViewGroup>()
/** 修复部分开发版状态栏图标只能显示一个的问题 */
when (miuiIncrementalVersion.lowercase()) {
"22.3.14", "22.3.15", "22.3.16", "v13.0.1.1.16.dev", "22.3.18" ->
@@ -740,14 +777,14 @@ class SystemUIHooker : YukiBaseHooker() {
.get(instance).set(prefs.get(DataConst.HOOK_STATUS_ICON_COUNT)
.let { if (it in 0..100) it else 5 })
}
}
}.by { NotificationIconContainerClass.clazz.hasField { name = "MAX_STATIC_ICONS" } }
/** 旧版方法 - 新版不存在 */
injectMember {
method {
name = "setMaxStaticIcons"
param(IntType)
}
beforeHook { isShowNotificationIcons = (firstArgs<Int>() ?: 0) > 0 }
beforeHook { isShowNotificationIcons = args().first().int() > 0 }
}.ignoredNoSuchMemberFailure()
/** 新版方法 - 旧版不存在 */
injectMember {
@@ -755,9 +792,9 @@ class SystemUIHooker : YukiBaseHooker() {
name = "miuiShowNotificationIcons"
param(BooleanType)
}
beforeHook { isShowNotificationIcons = firstArgs<Boolean>() ?: false }
beforeHook { isShowNotificationIcons = args().first().boolean() }
}.ignoredNoSuchMemberFailure()
}.by { NotificationIconContainerClass.clazz.hasField { name = "MAX_STATIC_ICONS" } }
}
/** 注入原生通知包装纸实例 */
NotificationHeaderViewWrapperClass.hook {
/** 修复下拉通知图标自动设置回 APP 图标的方法 */
@@ -769,29 +806,27 @@ class SystemUIHooker : YukiBaseHooker() {
/** 获取小图标 */
val iconImageView =
NotificationHeaderViewWrapperClass.clazz
.field { name = "mIcon" }.of<ImageView>(instance) ?: return@afterHook
.field { name = "mIcon" }.get(instance).cast<ImageView>() ?: return@afterHook
/** 获取 [ExpandableNotificationRowClass] */
val rowPair = instance.getRowPair()
/** 获取 [StatusBarNotification] */
val sbnPair = instance.getSbnPair()
val expandedNf = rowPair.second.getSbn()
/** 通知是否展开 */
var isExpanded = sbnPair.first
var isExpanded = rowPair.first
/** 获取优先级 */
val importance =
(iconImageView.context.getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager?)
?.getNotificationChannel(sbnPair.second?.notification?.channelId)?.importance ?: 0
?.getNotificationChannel(expandedNf?.notification?.channelId)?.importance ?: 0
/** 非最小化优先级的通知全部设置为展开状态 */
if (importance != 1) isExpanded = true
/** 执行 Hook */
compatNotifyIcon(iconImageView.context, sbnPair.second, iconImageView, isExpanded)
compatNotifyIcon(iconImageView.context, expandedNf, iconImageView, isExpanded)
}
}
/** 记录实例 */
injectMember {
constructor { param(ContextClass, ViewClass, ExpandableNotificationRowClass.clazz) }
afterHook { notificationViewWrappers.add(instance) }
}
}
/** 修改 MIUI 风格通知栏的通知图标 */
MiuiNotificationViewWrapperClass.hook {
@@ -799,15 +834,33 @@ class SystemUIHooker : YukiBaseHooker() {
injectMember {
method { name = "handleAppIcon" }
replaceUnit {
field { name = "mAppIcon" }.of<ImageView>(instance)?.apply {
compatNotifyIcon(context, instance.getSbnPair().second, iconImageView = this, isUseAndroid12Style = true)
field { name = "mAppIcon" }.get(instance).cast<ImageView>()?.apply {
compatNotifyIcon(
context = context,
expandedNf = instance.getRowPair().second.getSbn(),
iconImageView = this,
isUseAndroid12Style = true
)
}
}
}
/** 记录实例 */
}.ignoredHookClassNotFoundFailure()
/** 修改 MIUI 风格通知栏的通知图标 - 折叠通知 */
MiuiNotificationChildrenContainerClass.hook {
/** 替换通知小图标 */
injectMember {
constructor { param(ContextClass, ViewClass, ExpandableNotificationRowClass.clazz) }
afterHook { miuiNotificationViewWrappers.add(instance) }
method {
name = "updateAppIcon"
param(BooleanType)
}
afterHook {
val expandedNf = NotificationChildrenContainerClass.clazz.field {
name = "mContainingNotification"
}.get(instance).self.getSbn()
field { name = "mAppIcon" }.get(instance).cast<ImageView>()?.apply {
compatNotifyIcon(context, expandedNf, iconImageView = this, isUseAndroid12Style = true)
}
}
}
}.ignoredHookClassNotFoundFailure()
/** 干掉下拉通知图标自动设置回 APP 图标的方法 */
@@ -815,11 +868,11 @@ class SystemUIHooker : YukiBaseHooker() {
injectMember {
method {
name = "setAppIcon"
param(ContextClass, ImageViewClass, ExpandedNotificationClass.clazz)
param(ContextClass, ImageViewClass, ExpandedNotificationClass)
}.remedys {
method {
name = "setAppIcon"
param(ImageViewClass, ExpandedNotificationClass.clazz)
param(ImageViewClass, ExpandedNotificationClass)
}
}
intercept()
@@ -827,7 +880,7 @@ class SystemUIHooker : YukiBaseHooker() {
injectMember {
method {
name = "resetIconBgAndPaddings"
param(ImageViewClass, ExpandedNotificationClass.clazz)
param(ImageViewClass, ExpandedNotificationClass)
}
intercept()
}.ignoredNoSuchMemberFailure()
@@ -840,7 +893,7 @@ class SystemUIHooker : YukiBaseHooker() {
param(ContextClass, IntentClass)
}
afterHook {
if (isEnableHookColorNotifyIcon()) (lastArgs as? Intent)?.also {
if (isEnableHookColorNotifyIcon()) args().last().cast<Intent>()?.also {
if (it.action.equals(Intent.ACTION_PACKAGE_REPLACED).not() &&
it.getBooleanExtra(Intent.EXTRA_REPLACING, false)
) return@also
@@ -850,11 +903,11 @@ class SystemUIHooker : YukiBaseHooker() {
if (iconDatas.takeIf { e -> e.isNotEmpty() }
?.filter { e -> e.packageName == newPkgName }
.isNullOrEmpty()
) IconAdaptationTool.pushNewAppSupportNotify(firstArgs()!!, newPkgName)
) IconAdaptationTool.pushNewAppSupportNotify(args().first().cast()!!, newPkgName)
}
Intent.ACTION_PACKAGE_REMOVED ->
IconAdaptationTool.removeNewAppSupportNotify(
context = firstArgs()!!,
context = args().first().cast()!!,
packageName = it.data?.schemeSpecificPart ?: ""
)
}
@@ -867,13 +920,18 @@ class SystemUIHooker : YukiBaseHooker() {
injectMember {
method { name = "updateTime" }
afterHook {
instance<View>().context.also {
/** 注册广播 */
registerReceiver(it)
/** 注册定时监听 */
if (isEnableHookColorNotifyIcon() && prefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_AUTO))
IconAdaptationTool.prepareAutoUpdateIconRule(
context = instance<View>().context,
context = it,
timeSet = prefs.get(DataConst.NOTIFY_ICON_FIX_AUTO_TIME)
)
}
}
}
}.ignoredHookClassNotFoundFailure()
}
}

View File

@@ -45,7 +45,7 @@ class MaterialSwitch(context: Context, attrs: AttributeSet?) : SwitchCompat(cont
return ColorStateList(states, colors)
}
private val thumbColor get() = if (isSystemInDarkMode) 0xFF7C7C7C else 0xFFCCCCCC
private val thumbColor get() = if (context.isSystemInDarkMode) 0xFF7C7C7C else 0xFFCCCCCC
init {
trackDrawable = DrawableBuilder()

View File

@@ -39,7 +39,7 @@ import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.viewbinding.ViewBinding
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.highcapable.yukihookapi.annotation.DoNotUseField
import com.highcapable.yukihookapi.annotation.CauseProblemsApi
import com.highcapable.yukihookapi.hook.factory.method
import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass
@@ -71,7 +71,7 @@ class DialogBuilder(val context: Context, private val isUseBlackTheme: Boolean)
private var dialogInstance: Dialog? = null // 对话框实例
@DoNotUseField
@CauseProblemsApi
var customLayoutView: View? = null // 自定义布局
/**

View File

@@ -32,6 +32,7 @@ import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.res.Configuration
@@ -57,6 +58,7 @@ import java.io.ByteArrayOutputStream
import java.text.SimpleDateFormat
import java.util.*
/**
* 系统深色模式是否开启
* @return [Boolean] 是否开启
@@ -237,6 +239,14 @@ fun Context.findAppName(name: String) =
fun Context.findAppIcon(name: String) =
safeOfNull { packageManager?.getPackageInfo(name, 0)?.applicationInfo?.loadIcon(packageManager) }
/**
* 获取 APP 是否为 DEBUG 版本
* @param name APP 包名
* @return [Boolean]
*/
fun Context.isAppDebuggable(name: String) =
safeOfFalse { (packageManager?.getPackageInfo(name, 0)?.applicationInfo?.flags?.and(ApplicationInfo.FLAG_DEBUGGABLE) ?: 0) != 0 }
/**
* 对数值自动补零
* @return [String]
@@ -305,7 +315,20 @@ val Context.systemAccentColor
*/
val Context.wallpaperColor
get() = safeOfNan {
WallpaperManager.getInstance(this).getWallpaperColors(WallpaperManager.FLAG_SYSTEM)?.secondaryColor?.toArgb() ?: 0
WallpaperManager.getInstance(this).getWallpaperColors(WallpaperManager.FLAG_SYSTEM)?.primaryColor?.toArgb() ?: 0
}
/**
* 获取较浅的颜色
* @return [Int]
*/
val Int.brighter: Int
get() {
val hsv = FloatArray(3)
Color.colorToHSV(this, hsv)
hsv[1] = hsv[1] - 0.3f
hsv[2] = hsv[2] + 0.3f
return Color.HSVToColor(hsv)
}
/**
@@ -389,12 +412,19 @@ fun findPropString(key: String, default: String = "") = safeOf(default) {
}
/**
* 执行命令 - su
* 是否有 Root 权限
* @return [Boolean]
*/
val isRootAccess get() = safeOfFalse { Shell.rootAccess() }
/**
* 执行命令
* @param cmd 命令
* @param isSu 是否使用 Root 权限执行 - 默认:是
* @return [String] 执行结果
*/
fun execShellSu(cmd: String) = safeOfNothing {
Shell.su(cmd).exec().out.let {
fun execShell(cmd: String, isSu: Boolean = true) = safeOfNothing {
(if (isSu) Shell.su(cmd) else Shell.sh(cmd)).exec().out.let {
if (it.isNotEmpty()) it[0].trim() else ""
}
}

View File

@@ -116,6 +116,7 @@ object IconAdaptationTool {
* @param packageName 安装的 APP 包名
*/
fun pushNewAppSupportNotify(context: Context, packageName: String) {
if (context.isAppDebuggable(packageName)) return
context.getSystemService(NotificationManager::class.java)?.apply {
createNotificationChannel(
NotificationChannel(

View File

@@ -121,7 +121,7 @@ object IconRuleManagerTool {
cancelButton()
neutralButton(text = "自定义规则") {
context.showDialog {
title = "自定义规则"
title = "自定义规则(调试)"
val editText = bind<DiaSourceFromStringBinding>().diaSfsInputEdit.apply {
requestFocus()
invalidate()

View File

@@ -87,9 +87,9 @@ object SystemUITool {
"部分 MIUI 内测和开发版中使用了状态栏主题可能会发生主题失效的情况,这种情况请再重启一次即可。\n\n" +
"重启过程会黑屏并等待进入锁屏重新解锁。"
confirmButton {
execShellSu(cmd = "pgrep systemui").also { pid ->
execShell(cmd = "pgrep systemui").also { pid ->
if (pid.isNotBlank())
execShellSu(cmd = "kill -9 $pid")
execShell(cmd = "kill -9 $pid")
else toast(msg = "ROOT 权限获取失败")
}
}

View File

@@ -9,6 +9,17 @@
android:paddingRight="15dp"
tools:ignore="HardcodedText">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="17.5dp"
android:lineSpacingExtra="6dp"
android:text="此功能仅用于调试单条规则或多条规则,同步最新在线规则后这里的内容将会被覆盖清空。"
android:textColor="@color/colorTextDark"
android:textSize="13sp" />
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

View File

@@ -1,12 +1,13 @@
plugins {
id 'com.android.application' version '7.1.2' apply false
id 'com.android.library' version '7.1.2' apply false
id 'com.android.application' version '7.1.3' apply false
id 'com.android.library' version '7.1.3' apply false
id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
}
ext {
appVersionName = "2.2"
appVersionCode = 27
appVersionName = "2.5"
appVersionCode = 30
enableR8 = true
}
task clean(type: Delete) {