From 5eb26ba18319cf9069273b425f77108cf811d495 Mon Sep 17 00:00:00 2001 From: Timeline <53483352+Nep-Timeline@users.noreply.github.com> Date: Fri, 27 Mar 2026 13:57:54 +0800 Subject: [PATCH 1/5] fix: unable to overwrite the icon after expand notification --- .../notify/hook/entity/SystemUIHooker.kt | 77 ++++++++++++------- 1 file changed, 50 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/com/fankes/coloros/notify/hook/entity/SystemUIHooker.kt b/app/src/main/java/com/fankes/coloros/notify/hook/entity/SystemUIHooker.kt index 29c2a83..dff2181 100644 --- a/app/src/main/java/com/fankes/coloros/notify/hook/entity/SystemUIHooker.kt +++ b/app/src/main/java/com/fankes/coloros/notify/hook/entity/SystemUIHooker.kt @@ -76,6 +76,7 @@ import com.highcapable.kavaref.extension.VariousClass import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker import com.highcapable.yukihookapi.hook.factory.injectModuleAppResources import com.highcapable.yukihookapi.hook.log.YLog +import de.robv.android.xposed.XposedHelpers import top.defaults.drawabletoolbox.DrawableBuilder /** @@ -115,7 +116,7 @@ object SystemUIHooker : YukiBaseHooker() { /** 原生存在的类 */ private val MediaDataClass by lazyClassOrNull("${PackageName.SYSTEMUI}.media.MediaData") - + /** 原生存在的类 */ private val ViewConfigCoordinatorClass by lazyClassOrNull("${PackageName.SYSTEMUI}.statusbar.notification.collection.coordinator.ViewConfigCoordinator") @@ -145,7 +146,7 @@ object SystemUIHooker : YukiBaseHooker() { /** ColorOS 存在的类 - 旧版本不存在 */ private val OplusNotificationGroupTemplateWrapperClass by lazyClassOrNull("com.oplus.systemui.notification.row.oplusgroup.OplusNotificationGroupTemplateWrapper") - + /** 根据多个版本存在不同的包名相同的类 */ private val OplusNotificationIconAreaControllerClass by lazyClass( VariousClass( @@ -296,7 +297,7 @@ object SystemUIHooker : YukiBaseHooker() { name = "proxyOnContentUpdated" parameterCount = 1 } != null - + private val isNotificationPresenter get() = StatusBarNotificationPresenterClass.resolve().optional(silent = true) .firstMethodOrNull { @@ -315,15 +316,15 @@ object SystemUIHooker : YukiBaseHooker() { private fun loggerDebug(tag: String, context: Context, nf: StatusBarNotification?, isCustom: Boolean, isGrayscale: Boolean) { if (ConfigData.isEnableModuleLog) YLog.debug( msg = "(Processing $tag) ↓\n" + - "[Title]: ${nf?.notification?.extras?.getString(Notification.EXTRA_TITLE)}\n" + - "[Content]: ${nf?.notification?.extras?.getString(Notification.EXTRA_TEXT)}\n" + - "[App Name]: ${context.appNameOf(packageName = nf?.packageName ?: "")}\n" + - "[Package Name]: ${nf?.packageName}\n" + - "[Sender Package Name]: ${nf?.opPkg}\n" + - "[Custom Icon]: $isCustom\n" + - "[Grayscale Icon]: $isGrayscale\n" + - "[From System Push]: ${nf?.isOplusPush}\n" + - "[String]: ${nf?.notification}" + "[Title]: ${nf?.notification?.extras?.getString(Notification.EXTRA_TITLE)}\n" + + "[Content]: ${nf?.notification?.extras?.getString(Notification.EXTRA_TEXT)}\n" + + "[App Name]: ${context.appNameOf(packageName = nf?.packageName ?: "")}\n" + + "[Package Name]: ${nf?.packageName}\n" + + "[Sender Package Name]: ${nf?.opPkg}\n" + + "[Custom Icon]: $isCustom\n" + + "[Grayscale Icon]: $isGrayscale\n" + + "[From System Push]: ${nf?.isOplusPush}\n" + + "[String]: ${nf?.notification}" ) } @@ -876,17 +877,8 @@ object SystemUIHooker : YukiBaseHooker() { name = "proxyOnContentUpdated" parameterCount = 1 }?.hook()?.after { - val mBase = instance.asResolver().optional().firstMethodOrNull { - name = "getBase" - emptyParameters() - superclass() - }?.invokeQuietly() - val imageView = mBase?.asResolver()?.optional()?.firstFieldOrNull { - name = "mIcon" - type = ImageView::class - superclass() - }?.getQuietly() - imageView?.apply { + val imageView = XposedHelpers.getObjectField(XposedHelpers.callMethod(instance, "getBase"), "mIcon") as ImageView + imageView.apply { ExpandableNotificationRowClass.resolve().optional() .firstMethodOrNull { name = "getEntry" } ?.of(args[0])?.invokeQuietly()?.let { @@ -969,9 +961,9 @@ object SystemUIHooker : YukiBaseHooker() { name = "updateIconsForLayout" parameterCount = 1 }?.apply { way = 1 } - ?: firstMethodOrNull { - name = "updateIconsForLayout" - }?.apply { way = 2 })?.hook()?.after { + ?: firstMethodOrNull { + name = "updateIconsForLayout" + }?.apply { way = 2 })?.hook()?.after { when (way) { 2 -> notificationIconContainer = OplusNotificationIconAreaControllerClass.resolve().optional() .firstMethodOrNull { name = "getNotificationIcons" } @@ -998,6 +990,37 @@ object SystemUIHooker : YukiBaseHooker() { /** 替换通知图标和样式 */ NotificationHeaderViewWrapperClass.resolve().optional().apply { + method { + name { it == "updateExpandability" || it == "setExpanded" } + }.hookAll().before { + firstFieldOrNull { name = "mIcon" }?.of(instance)?.get()?.apply { + ExpandableNotificationRowClass.resolve().optional() + .firstMethodOrNull { name = "getEntry" } + ?.of(NotificationViewWrapperClass.resolve().optional().firstFieldOrNull { + name = "mRow" + }?.of(instance)?.get())?.invokeQuietly()?.let { + it.asResolver().optional().firstMethodOrNull { + name = "getSbn" + }?.invoke() + }.also { nf -> + nf?.notification?.also { + it.smallIcon.loadDrawable(context)?.also { iconDrawable -> + /** 执行替换 */ + compatNotifyIcon( + context = context, + nf = nf, + isGrayscaleIcon = isGrayscaleIcon(context, iconDrawable), + packageName = context.packageName, + drawable = iconDrawable, + iconColor = it.color, + iconView = this + ) + } + } + } + } + } + method { name { it == "resolveHeaderViews" || it == "onContentUpdated" } }.hookAll().after { @@ -1036,4 +1059,4 @@ object SystemUIHooker : YukiBaseHooker() { } } } -} +} \ No newline at end of file From d283e0854d49669709f4968cf04704cc8dce8a2e Mon Sep 17 00:00:00 2001 From: Timeline <53483352+Nep-Timeline@users.noreply.github.com> Date: Fri, 27 Mar 2026 14:02:07 +0800 Subject: [PATCH 2/5] opt: Intercept ColorOS notification icon detection --- .../coloros/notify/hook/entity/SystemUIHooker.kt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/fankes/coloros/notify/hook/entity/SystemUIHooker.kt b/app/src/main/java/com/fankes/coloros/notify/hook/entity/SystemUIHooker.kt index dff2181..7e533d7 100644 --- a/app/src/main/java/com/fankes/coloros/notify/hook/entity/SystemUIHooker.kt +++ b/app/src/main/java/com/fankes/coloros/notify/hook/entity/SystemUIHooker.kt @@ -739,9 +739,16 @@ object SystemUIHooker : YukiBaseHooker() { } } /** 拦截 ColorOS 使用应用图标判断 */ - OplusNotificationSmallIconUtilClass?.resolve()?.optional()?.firstMethodOrNull { - name = "useAppIconForSmallIcon" - parameters(Notification::class) + OplusNotificationSmallIconUtilClass?.resolve()?.optional()?.apply { + firstMethodOrNull { + name = "useAppIconForSmallIcon" + parameters(Notification::class) + }?.hook()?.before { + resultFalse() + } + } + Notification::class.java.resolve().optional().firstMethodOrNull { + name = "shouldUseAppIcon" }?.hook()?.before { resultFalse() } @@ -1020,7 +1027,7 @@ object SystemUIHooker : YukiBaseHooker() { } } } - + method { name { it == "resolveHeaderViews" || it == "onContentUpdated" } }.hookAll().after { From f3bbfb16574f0bae99d63e3e253a6c39c55b36b6 Mon Sep 17 00:00:00 2001 From: Timeline <53483352+Nep-Timeline@users.noreply.github.com> Date: Fri, 27 Mar 2026 17:32:41 +0800 Subject: [PATCH 3/5] fix: corner size --- app/src/main/res/layout/activity_main.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 508f38b..7c56901 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -583,9 +583,9 @@ android:layout_marginLeft="5dp" android:layout_marginTop="5dp" android:layout_marginRight="5dp" - android:max="10" + android:max="15" android:min="0" - android:progress="10" /> + android:progress="15" /> From 3745438b42b07b624c37e1ce3a075124519c1afe Mon Sep 17 00:00:00 2001 From: Timeline <53483352+Nep-Timeline@users.noreply.github.com> Date: Fri, 27 Mar 2026 21:10:57 +0800 Subject: [PATCH 4/5] fix: Handle icon expansion behavior --- .../notify/hook/entity/SystemUIHooker.kt | 76 +++++++++++++++++-- 1 file changed, 68 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/fankes/coloros/notify/hook/entity/SystemUIHooker.kt b/app/src/main/java/com/fankes/coloros/notify/hook/entity/SystemUIHooker.kt index 7e533d7..21eddca 100644 --- a/app/src/main/java/com/fankes/coloros/notify/hook/entity/SystemUIHooker.kt +++ b/app/src/main/java/com/fankes/coloros/notify/hook/entity/SystemUIHooker.kt @@ -34,6 +34,7 @@ import android.graphics.Color import android.graphics.Outline import android.graphics.drawable.Drawable import android.graphics.drawable.Icon +import android.os.Build import android.os.SystemClock import android.service.notification.StatusBarNotification import android.util.ArrayMap @@ -147,6 +148,9 @@ object SystemUIHooker : YukiBaseHooker() { /** ColorOS 存在的类 - 旧版本不存在 */ private val OplusNotificationGroupTemplateWrapperClass by lazyClassOrNull("com.oplus.systemui.notification.row.oplusgroup.OplusNotificationGroupTemplateWrapper") + /** ColorOS 存在的类 - 旧版本不存在 */ + private val OplusNotificationGroupExtImplClass by lazyClassOrNull("com.oplus.systemui.notification.row.oplusgroup.OplusNotificationGroupExtImpl") + /** 根据多个版本存在不同的包名相同的类 */ private val OplusNotificationIconAreaControllerClass by lazyClass( VariousClass( @@ -516,7 +520,8 @@ object SystemUIHooker : YukiBaseHooker() { packageName: String, drawable: Drawable, iconColor: Int, - iconView: ImageView + iconView: ImageView, + header: Boolean = false ) = runInSafe { compatCustomIcon(context, isGrayscaleIcon, packageName).also { customTriple -> when { @@ -563,11 +568,23 @@ object SystemUIHooker : YukiBaseHooker() { .solidColor(newApplyColor) .build() setColorFilter(newStyle) - setPadding(2.dp(context)) + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.VANILLA_ICE_CREAM) + if (header) + setPadding(3.2f.dp(context)) + else + setPadding(6.dp(context)) + else + setPadding(2.dp(context)) } else { background = null setColorFilter(oldApplyColor) - setPadding(0) + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.VANILLA_ICE_CREAM) + if (header) + setPadding(2.2f.dp(context)) + else + setPadding(4.dp(context)) + else + setPadding(0.dp(context)) } } else -> iconView.apply { @@ -747,11 +764,6 @@ object SystemUIHooker : YukiBaseHooker() { resultFalse() } } - Notification::class.java.resolve().optional().firstMethodOrNull { - name = "shouldUseAppIcon" - }?.hook()?.before { - resultFalse() - } /** 修复并替换 ColorOS 以及原生灰度图标色彩判断 */ NotificationUtilsClass.resolve().optional(silent = true).apply { firstMethodOrNull { @@ -878,6 +890,54 @@ object SystemUIHooker : YukiBaseHooker() { } if (isNewNotification) { + /** 阻止颜色覆盖 */ + OplusNotificationGroupExtImplClass?.resolve()?.optional()?.firstMethodOrNull { + name = "updateExpandIconColorFilter" + parameterCount = 1 + }?.hook()?.intercept() + /** 动态处理通知展开 */ + ExpandableNotificationRowClass.resolve().optional().apply { + firstMethodOrNull { + name = "onExpansionChanged" + parameterCount = 2 + }?.hook()?.before { + ExpandableNotificationRowClass.resolve().optional() + .firstFieldOrNull { name = "mChildrenContainer" } + ?.of(instance)?.getQuietly()?.let { + it.asResolver().optional().firstFieldOrNull { + name = "mCurrentHeader" + superclass() + }?.get() + }.also { header -> + header?.asResolver()?.optional()?.firstFieldOrNull { + name = "mIcon" + }?.get()?.apply { + ExpandableNotificationRowClass.resolve().optional() + .firstMethodOrNull { name = "getEntry" } + ?.of(instance)?.invokeQuietly()?.let { + it.asResolver().optional().firstMethodOrNull { + name = "getSbn" + }?.invoke() + }.also { nf -> + nf?.notification?.also { + it.smallIcon.loadDrawable(context)?.also { iconDrawable -> + compatNotifyIcon( + context = context, + nf = nf, + isGrayscaleIcon = isGrayscaleIcon(context, iconDrawable), + packageName = context.packageName, + drawable = iconDrawable, + iconColor = it.color, + iconView = this, + header = true + ) + } + } + } + } + } + } + } /** 替换通知图标和样式 */ OplusNotificationHeaderViewWrapperExImpClass?.resolve()?.optional()?.apply { firstMethodOrNull { From e7869c4add658cfc9b643d15bd47b17b7ba0d245 Mon Sep 17 00:00:00 2001 From: Timeline <53483352+Nep-Timeline@users.noreply.github.com> Date: Fri, 27 Mar 2026 21:13:40 +0800 Subject: [PATCH 5/5] why? --- app/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0503315..b5a51d5 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -51,7 +51,7 @@ androidComponents { it.outputs.forEach { output -> val currentType = it.buildType val currentSuffix = gropify.github.ci.commit.id.let { suffix -> - if (suffix.isNotBlank()) "-$suffix" else "" + if (!suffix.isBlank()) "-$suffix" else "" } val currentVersion = "${output.versionName.get()}$currentSuffix(${output.versionCode.get()})" if (output is com.android.build.api.variant.impl.VariantOutputImpl) @@ -78,4 +78,4 @@ dependencies { testImplementation(libs.junit) androidTestImplementation(libs.androidx.test.ext.junit) androidTestImplementation(libs.androidx.test.espresso.core) -} \ No newline at end of file +}