Skip to content

Commit 58679cb

Browse files
authored
fix: unable to override notification icon (#90)
1 parent 3cfbae8 commit 58679cb

3 files changed

Lines changed: 130 additions & 40 deletions

File tree

app/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ androidComponents {
5151
it.outputs.forEach { output ->
5252
val currentType = it.buildType
5353
val currentSuffix = gropify.github.ci.commit.id.let { suffix ->
54-
if (suffix.isNotBlank()) "-$suffix" else ""
54+
if (!suffix.isBlank()) "-$suffix" else ""
5555
}
5656
val currentVersion = "${output.versionName.get()}$currentSuffix(${output.versionCode.get()})"
5757
if (output is com.android.build.api.variant.impl.VariantOutputImpl)
@@ -78,4 +78,4 @@ dependencies {
7878
testImplementation(libs.junit)
7979
androidTestImplementation(libs.androidx.test.ext.junit)
8080
androidTestImplementation(libs.androidx.test.espresso.core)
81-
}
81+
}

app/src/main/java/com/fankes/coloros/notify/hook/entity/SystemUIHooker.kt

Lines changed: 125 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import android.graphics.Color
3434
import android.graphics.Outline
3535
import android.graphics.drawable.Drawable
3636
import android.graphics.drawable.Icon
37+
import android.os.Build
3738
import android.os.SystemClock
3839
import android.service.notification.StatusBarNotification
3940
import android.util.ArrayMap
@@ -76,6 +77,7 @@ import com.highcapable.kavaref.extension.VariousClass
7677
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
7778
import com.highcapable.yukihookapi.hook.factory.injectModuleAppResources
7879
import com.highcapable.yukihookapi.hook.log.YLog
80+
import de.robv.android.xposed.XposedHelpers
7981
import top.defaults.drawabletoolbox.DrawableBuilder
8082

8183
/**
@@ -115,7 +117,7 @@ object SystemUIHooker : YukiBaseHooker() {
115117

116118
/** 原生存在的类 */
117119
private val MediaDataClass by lazyClassOrNull("${PackageName.SYSTEMUI}.media.MediaData")
118-
120+
119121
/** 原生存在的类 */
120122
private val ViewConfigCoordinatorClass by lazyClassOrNull("${PackageName.SYSTEMUI}.statusbar.notification.collection.coordinator.ViewConfigCoordinator")
121123

@@ -145,7 +147,10 @@ object SystemUIHooker : YukiBaseHooker() {
145147

146148
/** ColorOS 存在的类 - 旧版本不存在 */
147149
private val OplusNotificationGroupTemplateWrapperClass by lazyClassOrNull("com.oplus.systemui.notification.row.oplusgroup.OplusNotificationGroupTemplateWrapper")
148-
150+
151+
/** ColorOS 存在的类 - 旧版本不存在 */
152+
private val OplusNotificationGroupExtImplClass by lazyClassOrNull("com.oplus.systemui.notification.row.oplusgroup.OplusNotificationGroupExtImpl")
153+
149154
/** 根据多个版本存在不同的包名相同的类 */
150155
private val OplusNotificationIconAreaControllerClass by lazyClass(
151156
VariousClass(
@@ -296,7 +301,7 @@ object SystemUIHooker : YukiBaseHooker() {
296301
name = "proxyOnContentUpdated"
297302
parameterCount = 1
298303
} != null
299-
304+
300305
private val isNotificationPresenter
301306
get() = StatusBarNotificationPresenterClass.resolve().optional(silent = true)
302307
.firstMethodOrNull {
@@ -315,15 +320,15 @@ object SystemUIHooker : YukiBaseHooker() {
315320
private fun loggerDebug(tag: String, context: Context, nf: StatusBarNotification?, isCustom: Boolean, isGrayscale: Boolean) {
316321
if (ConfigData.isEnableModuleLog) YLog.debug(
317322
msg = "(Processing $tag) ↓\n" +
318-
"[Title]: ${nf?.notification?.extras?.getString(Notification.EXTRA_TITLE)}\n" +
319-
"[Content]: ${nf?.notification?.extras?.getString(Notification.EXTRA_TEXT)}\n" +
320-
"[App Name]: ${context.appNameOf(packageName = nf?.packageName ?: "")}\n" +
321-
"[Package Name]: ${nf?.packageName}\n" +
322-
"[Sender Package Name]: ${nf?.opPkg}\n" +
323-
"[Custom Icon]: $isCustom\n" +
324-
"[Grayscale Icon]: $isGrayscale\n" +
325-
"[From System Push]: ${nf?.isOplusPush}\n" +
326-
"[String]: ${nf?.notification}"
323+
"[Title]: ${nf?.notification?.extras?.getString(Notification.EXTRA_TITLE)}\n" +
324+
"[Content]: ${nf?.notification?.extras?.getString(Notification.EXTRA_TEXT)}\n" +
325+
"[App Name]: ${context.appNameOf(packageName = nf?.packageName ?: "")}\n" +
326+
"[Package Name]: ${nf?.packageName}\n" +
327+
"[Sender Package Name]: ${nf?.opPkg}\n" +
328+
"[Custom Icon]: $isCustom\n" +
329+
"[Grayscale Icon]: $isGrayscale\n" +
330+
"[From System Push]: ${nf?.isOplusPush}\n" +
331+
"[String]: ${nf?.notification}"
327332
)
328333
}
329334

@@ -515,7 +520,8 @@ object SystemUIHooker : YukiBaseHooker() {
515520
packageName: String,
516521
drawable: Drawable,
517522
iconColor: Int,
518-
iconView: ImageView
523+
iconView: ImageView,
524+
header: Boolean = false
519525
) = runInSafe {
520526
compatCustomIcon(context, isGrayscaleIcon, packageName).also { customTriple ->
521527
when {
@@ -562,11 +568,23 @@ object SystemUIHooker : YukiBaseHooker() {
562568
.solidColor(newApplyColor)
563569
.build()
564570
setColorFilter(newStyle)
565-
setPadding(2.dp(context))
571+
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.VANILLA_ICE_CREAM)
572+
if (header)
573+
setPadding(3.2f.dp(context))
574+
else
575+
setPadding(6.dp(context))
576+
else
577+
setPadding(2.dp(context))
566578
} else {
567579
background = null
568580
setColorFilter(oldApplyColor)
569-
setPadding(0)
581+
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.VANILLA_ICE_CREAM)
582+
if (header)
583+
setPadding(2.2f.dp(context))
584+
else
585+
setPadding(4.dp(context))
586+
else
587+
setPadding(0.dp(context))
570588
}
571589
}
572590
else -> iconView.apply {
@@ -738,11 +756,13 @@ object SystemUIHooker : YukiBaseHooker() {
738756
}
739757
}
740758
/** 拦截 ColorOS 使用应用图标判断 */
741-
OplusNotificationSmallIconUtilClass?.resolve()?.optional()?.firstMethodOrNull {
742-
name = "useAppIconForSmallIcon"
743-
parameters(Notification::class)
744-
}?.hook()?.before {
745-
resultFalse()
759+
OplusNotificationSmallIconUtilClass?.resolve()?.optional()?.apply {
760+
firstMethodOrNull {
761+
name = "useAppIconForSmallIcon"
762+
parameters(Notification::class)
763+
}?.hook()?.before {
764+
resultFalse()
765+
}
746766
}
747767
/** 修复并替换 ColorOS 以及原生灰度图标色彩判断 */
748768
NotificationUtilsClass.resolve().optional(silent = true).apply {
@@ -870,23 +890,62 @@ object SystemUIHooker : YukiBaseHooker() {
870890
}
871891

872892
if (isNewNotification) {
893+
/** 阻止颜色覆盖 */
894+
OplusNotificationGroupExtImplClass?.resolve()?.optional()?.firstMethodOrNull {
895+
name = "updateExpandIconColorFilter"
896+
parameterCount = 1
897+
}?.hook()?.intercept()
898+
/** 动态处理通知展开 */
899+
ExpandableNotificationRowClass.resolve().optional().apply {
900+
firstMethodOrNull {
901+
name = "onExpansionChanged"
902+
parameterCount = 2
903+
}?.hook()?.before {
904+
ExpandableNotificationRowClass.resolve().optional()
905+
.firstFieldOrNull { name = "mChildrenContainer" }
906+
?.of(instance)?.getQuietly()?.let {
907+
it.asResolver().optional().firstFieldOrNull {
908+
name = "mCurrentHeader"
909+
superclass()
910+
}?.get()
911+
}.also { header ->
912+
header?.asResolver()?.optional()?.firstFieldOrNull {
913+
name = "mIcon"
914+
}?.get<ImageView>()?.apply {
915+
ExpandableNotificationRowClass.resolve().optional()
916+
.firstMethodOrNull { name = "getEntry" }
917+
?.of(instance)?.invokeQuietly()?.let {
918+
it.asResolver().optional().firstMethodOrNull {
919+
name = "getSbn"
920+
}?.invoke<StatusBarNotification>()
921+
}.also { nf ->
922+
nf?.notification?.also {
923+
it.smallIcon.loadDrawable(context)?.also { iconDrawable ->
924+
compatNotifyIcon(
925+
context = context,
926+
nf = nf,
927+
isGrayscaleIcon = isGrayscaleIcon(context, iconDrawable),
928+
packageName = context.packageName,
929+
drawable = iconDrawable,
930+
iconColor = it.color,
931+
iconView = this,
932+
header = true
933+
)
934+
}
935+
}
936+
}
937+
}
938+
}
939+
}
940+
}
873941
/** 替换通知图标和样式 */
874942
OplusNotificationHeaderViewWrapperExImpClass?.resolve()?.optional()?.apply {
875943
firstMethodOrNull {
876944
name = "proxyOnContentUpdated"
877945
parameterCount = 1
878946
}?.hook()?.after {
879-
val mBase = instance.asResolver().optional().firstMethodOrNull {
880-
name = "getBase"
881-
emptyParameters()
882-
superclass()
883-
}?.invokeQuietly()
884-
val imageView = mBase?.asResolver()?.optional()?.firstFieldOrNull {
885-
name = "mIcon"
886-
type = ImageView::class
887-
superclass()
888-
}?.getQuietly<ImageView>()
889-
imageView?.apply {
947+
val imageView = XposedHelpers.getObjectField(XposedHelpers.callMethod(instance, "getBase"), "mIcon") as ImageView
948+
imageView.apply {
890949
ExpandableNotificationRowClass.resolve().optional()
891950
.firstMethodOrNull { name = "getEntry" }
892951
?.of(args[0])?.invokeQuietly()?.let {
@@ -969,9 +1028,9 @@ object SystemUIHooker : YukiBaseHooker() {
9691028
name = "updateIconsForLayout"
9701029
parameterCount = 1
9711030
}?.apply { way = 1 }
972-
?: firstMethodOrNull {
973-
name = "updateIconsForLayout"
974-
}?.apply { way = 2 })?.hook()?.after {
1031+
?: firstMethodOrNull {
1032+
name = "updateIconsForLayout"
1033+
}?.apply { way = 2 })?.hook()?.after {
9751034
when (way) {
9761035
2 -> notificationIconContainer = OplusNotificationIconAreaControllerClass.resolve().optional()
9771036
.firstMethodOrNull { name = "getNotificationIcons" }
@@ -998,6 +1057,37 @@ object SystemUIHooker : YukiBaseHooker() {
9981057

9991058
/** 替换通知图标和样式 */
10001059
NotificationHeaderViewWrapperClass.resolve().optional().apply {
1060+
method {
1061+
name { it == "updateExpandability" || it == "setExpanded" }
1062+
}.hookAll().before {
1063+
firstFieldOrNull { name = "mIcon" }?.of(instance)?.get<ImageView>()?.apply {
1064+
ExpandableNotificationRowClass.resolve().optional()
1065+
.firstMethodOrNull { name = "getEntry" }
1066+
?.of(NotificationViewWrapperClass.resolve().optional().firstFieldOrNull {
1067+
name = "mRow"
1068+
}?.of(instance)?.get())?.invokeQuietly()?.let {
1069+
it.asResolver().optional().firstMethodOrNull {
1070+
name = "getSbn"
1071+
}?.invoke<StatusBarNotification>()
1072+
}.also { nf ->
1073+
nf?.notification?.also {
1074+
it.smallIcon.loadDrawable(context)?.also { iconDrawable ->
1075+
/** 执行替换 */
1076+
compatNotifyIcon(
1077+
context = context,
1078+
nf = nf,
1079+
isGrayscaleIcon = isGrayscaleIcon(context, iconDrawable),
1080+
packageName = context.packageName,
1081+
drawable = iconDrawable,
1082+
iconColor = it.color,
1083+
iconView = this
1084+
)
1085+
}
1086+
}
1087+
}
1088+
}
1089+
}
1090+
10011091
method {
10021092
name { it == "resolveHeaderViews" || it == "onContentUpdated" }
10031093
}.hookAll().after {
@@ -1036,4 +1126,4 @@ object SystemUIHooker : YukiBaseHooker() {
10361126
}
10371127
}
10381128
}
1039-
}
1129+
}

app/src/main/res/layout/activity_main.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -583,9 +583,9 @@
583583
android:layout_marginLeft="5dp"
584584
android:layout_marginTop="5dp"
585585
android:layout_marginRight="5dp"
586-
android:max="10"
586+
android:max="15"
587587
android:min="0"
588-
android:progress="10" />
588+
android:progress="15" />
589589

590590
<LinearLayout
591591
android:layout_width="match_parent"
@@ -616,7 +616,7 @@
616616
android:gravity="center"
617617
android:maxWidth="100dp"
618618
android:singleLine="true"
619-
android:text="10 dp"
619+
android:text="15 dp"
620620
android:textColor="@color/colorTextGray"
621621
android:textSize="15sp"
622622
android:textStyle="bold" />

0 commit comments

Comments
 (0)