Skip to content

Commit 51cff05

Browse files
Nep-Timelinefankes
andauthored
fix: The onContentUpdated hook does not work on ColorOS 16 (#85)
* fix: block coloros 15 fixSmallIcon method * fix: hook error * feat: complete ColorOS 15 support * docs: update README * misc: Add API 35 and API 36 to androidVersions CodeName * fix: The onContentUpdated hook does not work on ColorOS 16 * refactor: update code style --------- Co-authored-by: fankesyooni <qzmmcn@163.com>
1 parent 172340d commit 51cff05

File tree

2 files changed

+173
-65
lines changed

2 files changed

+173
-65
lines changed

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

Lines changed: 171 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import android.widget.ImageView
4444
import androidx.core.graphics.drawable.toBitmap
4545
import androidx.core.graphics.drawable.toDrawable
4646
import androidx.core.view.children
47+
import androidx.core.view.setPadding
4748
import com.fankes.coloros.notify.R
4849
import com.fankes.coloros.notify.bean.IconDataBean
4950
import com.fankes.coloros.notify.const.PackageName
@@ -136,6 +137,12 @@ object SystemUIHooker : YukiBaseHooker() {
136137
/** ColorOS 存在的类 - 旧版本不存在 */
137138
private val OplusNotificationSmallIconUtilClass by lazyClassOrNull("com.oplus.systemui.statusbar.notification.util.OplusNotificationSmallIconUtil")
138139

140+
/** ColorOS 存在的类 - 旧版本不存在 */
141+
private val OplusNotificationHeaderViewWrapperExImpClass by lazyClassOrNull("com.oplus.systemui.statusbar.notification.row.wrapper.OplusNotificationHeaderViewWrapperExImp")
142+
143+
/** ColorOS 存在的类 - 旧版本不存在 */
144+
private val OplusNotificationGroupTemplateWrapperClass by lazyClassOrNull("com.oplus.systemui.notification.row.oplusgroup.OplusNotificationGroupTemplateWrapper")
145+
139146
/** 根据多个版本存在不同的包名相同的类 */
140147
private val OplusNotificationIconAreaControllerClass by lazyClass(
141148
VariousClass(
@@ -276,6 +283,17 @@ object SystemUIHooker : YukiBaseHooker() {
276283
parameterCount = 2
277284
} != null
278285

286+
/**
287+
* 判断通知是否为新版本
288+
* @return [Boolean]
289+
*/
290+
private val isNewNotification
291+
get() = OplusNotificationHeaderViewWrapperExImpClass?.resolve()?.optional(silent = true)
292+
?.firstMethodOrNull {
293+
name = "proxyOnContentUpdated"
294+
parameterCount = 1
295+
} != null
296+
279297
/**
280298
* 打印日志
281299
* @param tag 标识
@@ -314,6 +332,7 @@ object SystemUIHooker : YukiBaseHooker() {
314332

315333
/** 刷新状态栏小图标 */
316334
private fun refreshStatusBarIcons() = runInSafe {
335+
if (isNewNotification) return@runInSafe
317336
val nfField = StatusBarIconViewClass.resolve().optional().firstFieldOrNull { name = "mNotification" }
318337
val sRadiusField = StatusBarIconViewClass.resolve().optional(silent = true).firstFieldOrNull {
319338
name = "sIconRadiusFraction"
@@ -533,11 +552,11 @@ object SystemUIHooker : YukiBaseHooker() {
533552
.solidColor(newApplyColor)
534553
.build()
535554
setColorFilter(newStyle)
536-
setPadding(2.dp(context), 2.dp(context), 2.dp(context), 2.dp(context))
555+
setPadding(2.dp(context))
537556
} else {
538557
background = null
539558
setColorFilter(oldApplyColor)
540-
setPadding(0, 0, 0, 0)
559+
setPadding(0)
541560
}
542561
}
543562
else -> iconView.apply {
@@ -599,7 +618,7 @@ object SystemUIHooker : YukiBaseHooker() {
599618
}
600619
}
601620
/** 清除图标间距 */
602-
setPadding(0, 0, 0, 0)
621+
setPadding(0)
603622
/** 清除背景 */
604623
background = null
605624
/** 清除着色 */
@@ -767,46 +786,6 @@ object SystemUIHooker : YukiBaseHooker() {
767786
}
768787
/** 注入通知控制器实例 */
769788
StatusBarNotificationPresenterClass.resolve().optional().constructor {}.hookAll().after { notificationPresenter = instance }
770-
/** 注入状态栏通知图标容器实例 */
771-
OplusNotificationIconAreaControllerClass.resolve().optional().apply {
772-
var way = 0
773-
(firstMethodOrNull {
774-
name = "updateIconsForLayout"
775-
parameterCount = 10
776-
} ?: firstMethodOrNull {
777-
/** ColorOS 14 */
778-
name = "updateIconsForLayout"
779-
parameterCount = 5
780-
} ?: firstMethodOrNull {
781-
name = "updateIconsForLayout"
782-
parameterCount = 1
783-
}?.apply { way = 1 }
784-
?: firstMethodOrNull {
785-
name = "updateIconsForLayout"
786-
}?.apply { way = 2 })?.hook()?.after {
787-
when (way) {
788-
2 -> notificationIconContainer = OplusNotificationIconAreaControllerClass.resolve().optional()
789-
.firstMethodOrNull { name = "getNotificationIcons" }
790-
?.of(instance)?.invoke<ViewGroup>()
791-
1 -> {
792-
notificationIconInstances.clear()
793-
firstFieldOrNull { name = "mLastToShow" }?.of(instance)?.get<List<View>>()
794-
?.takeIf { it.isNotEmpty() }?.forEach { notificationIconInstances.add(it) }
795-
}
796-
else -> notificationIconContainer = args(index = 1).cast()
797-
}
798-
}
799-
}
800-
/** 注入状态栏通知图标容器实例 */
801-
(LegacyNotificationIconAreaControllerImpl ?: NotificationIconAreaControllerClass)
802-
.resolve().optional().apply {
803-
firstMethodOrNull {
804-
name = "updateIconsForLayout"
805-
parameterCount = 8
806-
}?.hook()?.after {
807-
notificationIconContainer = args(index = 1).cast()
808-
}
809-
}
810789
/** 替换通知面板背景 - 新版本 */
811790
if (!isOldNotificationBackground)
812791
OplusNotificationBackgroundViewClass?.resolve()?.optional()?.apply {
@@ -876,25 +855,75 @@ object SystemUIHooker : YukiBaseHooker() {
876855
}?.of(holder)?.invokeQuietly<View>()?.performClick()
877856
}
878857
}
879-
/** 替换通知图标和样式 */
880-
NotificationHeaderViewWrapperClass.resolve().optional().apply {
881-
method {
882-
name { it == "resolveHeaderViews" || it == "onContentUpdated" }
883-
}.hookAll().after {
884-
firstFieldOrNull { name = "mIcon" }?.of(instance)?.get<ImageView>()?.apply {
885-
ExpandableNotificationRowClass.resolve().optional()
886-
.firstMethodOrNull { name = "getEntry" }
887-
?.of(NotificationViewWrapperClass.resolve().optional().firstFieldOrNull {
888-
name = "mRow"
889-
}?.of(instance)?.get())?.invokeQuietly()?.let {
890-
it.asResolver().optional().firstMethodOrNull {
891-
name = "getSbn"
892-
}?.invoke<StatusBarNotification>()
893-
}.also { nf ->
894-
nf?.notification?.also {
895-
it.smallIcon.loadDrawable(context)?.also { iconDrawable ->
896-
/** 执行替换 */
897-
fun doParse() {
858+
859+
if (isNewNotification) {
860+
/** 替换通知图标和样式 */
861+
OplusNotificationHeaderViewWrapperExImpClass?.resolve()?.optional()?.apply {
862+
firstMethodOrNull {
863+
name = "proxyOnContentUpdated"
864+
parameterCount = 1
865+
}?.hook()?.after {
866+
val mBase = instance.asResolver().optional().firstMethodOrNull {
867+
name = "getBase"
868+
emptyParameters()
869+
}?.invokeQuietly()
870+
val imageView = mBase?.asResolver()?.optional()?.firstFieldOrNull {
871+
name = "mIcon"
872+
type = ImageView::class
873+
}?.getQuietly<ImageView>()
874+
imageView?.apply {
875+
ExpandableNotificationRowClass.resolve().optional()
876+
.firstMethodOrNull { name = "getEntry" }
877+
?.of(args[0])?.invokeQuietly()?.let {
878+
it.asResolver().optional().firstMethodOrNull {
879+
name = "getSbn"
880+
}?.invoke<StatusBarNotification>()
881+
}.also { nf ->
882+
nf?.notification?.also {
883+
it.smallIcon.loadDrawable(context)?.also { iconDrawable ->
884+
compatNotifyIcon(
885+
context = context,
886+
nf = nf,
887+
isGrayscaleIcon = isGrayscaleIcon(context, iconDrawable),
888+
packageName = context.packageName,
889+
drawable = iconDrawable,
890+
iconColor = it.color,
891+
iconView = this
892+
)
893+
}
894+
}
895+
}
896+
}
897+
}
898+
}
899+
900+
OplusNotificationGroupTemplateWrapperClass?.resolve()?.optional()?.apply {
901+
firstMethodOrNull {
902+
name = "initIcon"
903+
}?.hook()?.before {
904+
val instanceContext = firstFieldOrNull {
905+
name = "context"
906+
}?.of(instance)?.get() as Context?
907+
if (instanceContext == null)
908+
return@before
909+
resultNull()
910+
NotificationHeaderViewWrapperClass.resolve().optional().firstFieldOrNull { name = "mIcon" }?.of(instance)?.get<ImageView>()?.apply {
911+
ExpandableNotificationRowClass.resolve().optional()
912+
.firstMethodOrNull { name = "getEntry" }
913+
?.of(NotificationViewWrapperClass.resolve().optional().firstFieldOrNull {
914+
name = "mRow"
915+
}?.of(instance)?.get())?.invokeQuietly()?.let {
916+
it.asResolver().optional().firstMethodOrNull {
917+
name = "getSbn"
918+
}?.invoke<StatusBarNotification>()
919+
}.also { nf ->
920+
val context = StatusBarNotification::class.resolve().firstMethod {
921+
name = "getPackageContext"
922+
}.of(nf).invoke<Context>(instanceContext)
923+
if (context == null) return@also
924+
925+
nf?.notification?.also {
926+
it.smallIcon.loadDrawable(context)?.also { iconDrawable ->
898927
compatNotifyIcon(
899928
context = context,
900929
nf = nf,
@@ -905,12 +934,89 @@ object SystemUIHooker : YukiBaseHooker() {
905934
iconView = this
906935
)
907936
}
908-
doParse()
909-
/** 延迟重新设置防止部分机型的系统重新设置图标出现图标着色后黑白块问题 */
910-
delayedRun(ms = 1500) { doParse() }
911937
}
912938
}
939+
}
940+
}
941+
}
942+
} else {
943+
/** 注入状态栏通知图标容器实例 */
944+
OplusNotificationIconAreaControllerClass.resolve().optional().apply {
945+
var way = 0
946+
(firstMethodOrNull {
947+
name = "updateIconsForLayout"
948+
parameterCount = 10
949+
} ?: firstMethodOrNull {
950+
/** ColorOS 14 */
951+
name = "updateIconsForLayout"
952+
parameterCount = 5
953+
} ?: firstMethodOrNull {
954+
name = "updateIconsForLayout"
955+
parameterCount = 1
956+
}?.apply { way = 1 }
957+
?: firstMethodOrNull {
958+
name = "updateIconsForLayout"
959+
}?.apply { way = 2 })?.hook()?.after {
960+
when (way) {
961+
2 -> notificationIconContainer = OplusNotificationIconAreaControllerClass.resolve().optional()
962+
.firstMethodOrNull { name = "getNotificationIcons" }
963+
?.of(instance)?.invoke<ViewGroup>()
964+
1 -> {
965+
notificationIconInstances.clear()
966+
firstFieldOrNull { name = "mLastToShow" }?.of(instance)?.get<List<View>>()
967+
?.takeIf { it.isNotEmpty() }?.forEach { notificationIconInstances.add(it) }
913968
}
969+
else -> notificationIconContainer = args(index = 1).cast()
970+
}
971+
}
972+
}
973+
/** 注入状态栏通知图标容器实例 */
974+
(LegacyNotificationIconAreaControllerImpl ?: NotificationIconAreaControllerClass)
975+
.resolve().optional().apply {
976+
firstMethodOrNull {
977+
name = "updateIconsForLayout"
978+
parameterCount = 8
979+
}?.hook()?.after {
980+
notificationIconContainer = args(index = 1).cast()
981+
}
982+
}
983+
984+
/** 替换通知图标和样式 */
985+
NotificationHeaderViewWrapperClass.resolve().optional().apply {
986+
method {
987+
name { it == "resolveHeaderViews" || it == "onContentUpdated" }
988+
}.hookAll().after {
989+
firstFieldOrNull { name = "mIcon" }?.of(instance)?.get<ImageView>()?.apply {
990+
ExpandableNotificationRowClass.resolve().optional()
991+
.firstMethodOrNull { name = "getEntry" }
992+
?.of(NotificationViewWrapperClass.resolve().optional().firstFieldOrNull {
993+
name = "mRow"
994+
}?.of(instance)?.get())?.invokeQuietly()?.let {
995+
it.asResolver().optional().firstMethodOrNull {
996+
name = "getSbn"
997+
}?.invoke<StatusBarNotification>()
998+
}.also { nf ->
999+
nf?.notification?.also {
1000+
it.smallIcon.loadDrawable(context)?.also { iconDrawable ->
1001+
/** 执行替换 */
1002+
fun doParse() {
1003+
compatNotifyIcon(
1004+
context = context,
1005+
nf = nf,
1006+
isGrayscaleIcon = isGrayscaleIcon(context, iconDrawable),
1007+
packageName = context.packageName,
1008+
drawable = iconDrawable,
1009+
iconColor = it.color,
1010+
iconView = this
1011+
)
1012+
}
1013+
doParse()
1014+
/** 延迟重新设置防止部分机型的系统重新设置图标出现图标着色后黑白块问题 */
1015+
delayedRun(ms = 1500) { doParse() }
1016+
}
1017+
}
1018+
}
1019+
}
9141020
}
9151021
}
9161022
}

app/src/main/java/com/fankes/coloros/notify/utils/factory/FunctionFactory.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ val isRealmeUI
150150
*/
151151
val androidVersionCodeName
152152
get() = when (Build.VERSION.SDK_INT) {
153+
36 -> "B"
154+
35 -> "V"
153155
34 -> "U"
154156
33 -> "T"
155157
32 -> "S_V2"

0 commit comments

Comments
 (0)