14 Commits
1.5 ... 1.53

Author SHA1 Message Date
1f2b1d5046 Update version to 1.53 2022-04-04 23:22:10 +08:00
7896e4836c Update YukiHookAPI 2022-04-04 23:13:24 +08:00
d2ff1fe3ec 修复 ColorOS 11 Android 11 上的问题 2022-04-04 23:12:58 +08:00
f5722e3e5c Update version to 1.52 2022-04-04 14:49:03 +08:00
44e99cb3da 修复缓存图标过大造成系统界面停止运行的问题 2022-04-04 14:45:56 +08:00
1386833c91 Merge code 2022-04-04 12:03:58 +08:00
69af0172eb Update YukiHookAPI 2022-04-04 03:19:41 +08:00
81e66d2da2 Update README.md 2022-03-30 20:56:21 +08:00
73a9142e71 Merge code 2022-03-30 14:14:23 +08:00
5af6ffb614 Merge code 2022-03-29 23:04:16 +08:00
230b3b4e38 Merge code 2022-03-29 21:45:19 +08:00
66f309dc91 Update version to 1.51 2022-03-29 21:21:02 +08:00
d4f004894e Update YukiHookAPI 2022-03-29 21:17:09 +08:00
f2e27c2702 Update version to 1.5 2022-03-28 14:50:57 +08:00
10 changed files with 111 additions and 53 deletions

View File

@@ -2,7 +2,7 @@
[![Blank](https://img.shields.io/badge/build-passing-brightgreen)](https://github.com/fankes/ColorOSNotifyIcon)
[![Blank](https://img.shields.io/badge/license-AGPL3.0-blue)](https://github.com/fankes/ColorOSNotifyIcon/blob/master/LICENSE)
[![Blank](https://img.shields.io/badge/version-v1.5-green)](https://github.com/fankes/ColorOSNotifyIcon/releases)
[![Blank](https://img.shields.io/badge/version-v1.53-green)](https://github.com/fankes/ColorOSNotifyIcon/releases)
[![Blank](https://img.shields.io/github/downloads/fankes/ColorOSNotifyIcon/total?label=Release)](https://github.com/fankes/ColorOSNotifyIcon/releases)
[![Blank](https://img.shields.io/github/downloads/Xposed-Modules-Repo/com.fankes.coloros.notify/total?label=LSPosed%20Repo&logo=Android&style=flat&labelColor=F48FB1&logoColor=ffffff)](https://github.com/Xposed-Modules-Repo/com.fankes.coloros.notify/releases)
[![Telegram](https://img.shields.io/static/v1?label=Telegram&message=交流讨论&color=0088cc)](https://t.me/XiaofangInternet)
@@ -40,6 +40,11 @@ Optimize notification icons for ColorOS and adapt to native notification icon sp
继 MIUI 之后的第二大系统 ColorOS 虽然支持原生通知图标,但是第三方推送五颜六色的图标系统并没有做适配,甚至系统自己的图标都是彩色的,极其不友好。<br/>
而且从 ColorOS 12 开始,原生图标丢失了着色属性,这也是一种对原生 Android 生态的破坏。
# 捐赠支持
- 工作不易,无意外情况此项目将继续维护下去,提供更多可能,欢迎打赏。<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)

View File

@@ -1,7 +1,7 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.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 {
@@ -44,11 +44,11 @@ android {
}
}
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.71'
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.71'
implementation 'com.github.tiann:FreeReflection:3.1.0'
implementation "com.github.topjohnwu.libsu:core:3.1.2"
implementation 'androidx.annotation:annotation:1.3.0'

View File

@@ -35,6 +35,8 @@
-renamesourcefileattribute P
-keepattributes SourceFile,LineNumberTable
-keep class me.weishu**{*;}
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service

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}_202203281333"
const val MODULE_VERSION_VERIFY = "${MODULE_VERSION_NAME}_${MODULE_VERSION_CODE}_202204042319"
/** 当前模块的版本校验标签 */
const val MODULE_VERSION_VERIFY_TAG = "module_version_verify"

View File

@@ -20,8 +20,6 @@
*
* This file is Created by fankes on 2022/3/25.
*/
@file:Suppress("Recycle")
package com.fankes.coloros.notify.hook.entity
import android.app.WallpaperManager
@@ -37,10 +35,14 @@ import android.graphics.drawable.Drawable
import android.graphics.drawable.Icon
import android.graphics.drawable.VectorDrawable
import android.service.notification.StatusBarNotification
import android.util.ArrayMap
import android.util.ArraySet
import android.view.View
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.coloros.notify.bean.IconDataBean
import com.fankes.coloros.notify.const.Const
import com.fankes.coloros.notify.data.DataConst
@@ -76,33 +78,40 @@ class SystemUIHooker : YukiBaseHooker() {
private const val ContrastColorUtilClass = "com.android.internal.util.ContrastColorUtil"
/** 原生存在的类 */
private const val NotificationUtilsClass = "${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.NotificationUtils"
private const val NotificationUtilsClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationUtils"
/** 原生存在的类 */
private const val NotificationEntryClass = "${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.collection.NotificationEntry"
private const val NotificationEntryClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.collection.NotificationEntry"
/** 原生存在的类 */
private const val StatusBarIconClass = "com.android.internal.statusbar.StatusBarIcon"
/** 原生存在的类 */
private const val StatusBarIconViewClass = "${SYSTEMUI_PACKAGE_NAME}.statusbar.StatusBarIconView"
private const val StatusBarIconViewClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.StatusBarIconView"
/** 原生存在的类 */
private const val IconBuilderClass = "${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.icon.IconBuilder"
private const val IconBuilderClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.icon.IconBuilder"
/** 原生存在的类 */
private const val IconManagerClass = "${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.icon.IconManager"
private const val IconManagerClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.icon.IconManager"
/** ColorOS 存在的类 - 旧版本不存在 */
private const val OplusContrastColorUtilClass = "com.oplusos.util.OplusContrastColorUtil"
/** 原生存在的类 */
private const val PluginManagerImplClass = "${SYSTEMUI_PACKAGE_NAME}.shared.plugins.PluginManagerImpl"
private const val PluginManagerImplClass = "$SYSTEMUI_PACKAGE_NAME.shared.plugins.PluginManagerImpl"
/** 根据多个版本存在不同的包名相同的类 */
private val OplusNotificationIconAreaControllerClass = VariousClass(
"com.oplusos.systemui.statusbar.phone.OplusNotificationIconAreaController",
"com.oplusos.systemui.statusbar.policy.OplusNotificationIconAreaController",
"com.coloros.systemui.statusbar.policy.ColorNotificationIconAreaController"
)
/** 根据多个版本存在不同的包名相同的类 */
private val SystemPromptControllerClass = VariousClass(
"com.oplusos.systemui.statusbar.policy.SystemPromptController",
"com.coloros.systemui.statusbar.policy.SystemPromptController"
"com.coloros.systemui.statusbar.policy.ColorSystemPromptController"
)
/** 根据多个版本存在不同的包名相同的类 */
@@ -137,34 +146,37 @@ class SystemUIHooker : YukiBaseHooker() {
/** 根据多个版本存在不同的包名相同的类 */
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"
)
}
/** 缓存的彩色 APP 图标 */
private var appIcons = HashMap<String, Drawable>()
private var appIcons = ArrayMap<String, Drawable>()
/** 缓存的通知优化图标数组 */
private var iconDatas = ArrayList<IconDataBean>()
/** 缓存的状态栏小图标实例 */
private var statusBarIconViews = HashSet<ImageView>()
/** 状态栏通知图标容器 */
private var notificationIconContainer: ViewGroup? = null
/** 状态栏通知图标数组 */
private var notificationIconInstances = ArrayList<View>()
/** 缓存的通知小图标包装纸实例 */
private var notificationViewWrappers = HashSet<Any>()
private var notificationViewWrappers = ArraySet<Any>()
/** 仅监听一次主题壁纸颜色变化 */
private var isWallpaperColorListenerSetUp = false
@@ -292,10 +304,10 @@ class SystemUIHooker : YukiBaseHooker() {
.get(RoundRectDrawableUtilClass.clazz.field { name = "Companion" }.get().self)
/** 启动一个线程防止卡顿 */
Thread {
statusBarIconViews.takeIf { it.isNotEmpty() }?.forEach {
(notificationIconContainer?.children?.toList() ?: notificationIconInstances.takeIf { it.isNotEmpty() })?.forEach {
runInSafe {
/** 得到通知实例 */
val nf = nfField.of<StatusBarNotification>(it) ?: return@Thread
val nf = nfField.get(it).cast<StatusBarNotification>() ?: return@Thread
/** 得到原始通知图标 */
val iconDrawable = nf.notification.smallIcon.loadDrawable(it.context)
@@ -308,12 +320,12 @@ class SystemUIHooker : YukiBaseHooker() {
drawable = iconDrawable
).also { pair ->
/** 得到图标圆角 */
val sRadius = sRadiusField.ofFloat(it)
val sRadius = sRadiusField.get(it).float()
/** 得到缩放大小 */
val sNfSize = sNfSizeField.ofInt(it)
val sNfSize = sNfSizeField.get(it).int()
/** 在主线程设置图标 */
it.post { it.setImageDrawable(roundUtil.invoke(pair.first, sRadius, sNfSize, sNfSize, it.context)) }
it.post { (it as? ImageView?)?.setImageDrawable(roundUtil.invoke(pair.first, sRadius, sNfSize, sNfSize, it.context)) }
}
}
}
@@ -343,7 +355,7 @@ class SystemUIHooker : YukiBaseHooker() {
}.get(it.method {
name = "getInstance"
param(ContextClass)
}.get().invoke(context)).callBoolean(drawable)
}.get().invoke(context)).boolean(drawable)
}
/**
@@ -537,7 +549,7 @@ class SystemUIHooker : YukiBaseHooker() {
}
beforeHook {
/** 是否移除 */
if (args().ofInt() == 7 && prefs.get(DataConst.REMOVE_CHANGECP_NOTIFY)) resultNull()
if (args().int() == 7 && prefs.get(DataConst.REMOVE_CHANGECP_NOTIFY)) resultNull()
}
}
}
@@ -554,12 +566,12 @@ class SystemUIHooker : YukiBaseHooker() {
}
}
}
/** 修复并替换新版本 ColorOS 原生灰度图标色彩判断*/
/** 修复并替换新版本 ColorOS 原生灰度图标色彩判断 */
NotificationUtilsClass.hook {
injectMember {
method {
name = "isGrayscaleOplus"
param(ImageViewClass, OplusContrastColorUtilClass.clazz)
param(ImageViewClass, OplusContrastColorUtilClass)
}
replaceAny { firstArgs<ImageView>()?.let { isGrayscaleIcon(it.context, it.drawable) } }
}.ignoredHookingFailure()
@@ -569,11 +581,11 @@ class SystemUIHooker : YukiBaseHooker() {
injectMember {
method {
name = "getIconDescriptor"
param(NotificationEntryClass.clazz, BooleanType)
param(NotificationEntryClass, BooleanType)
}
afterHook {
IconBuilderClass.clazz.field { name = "context" }
.of<Context>(field { name = "iconBuilder" }.of(instance))?.also { context ->
.get(field { name = "iconBuilder" }.get(instance).cast()).cast<Context>()?.also { context ->
NotificationEntryClass.clazz.method {
name = "getSbn"
}.get(firstArgs).invoke<StatusBarNotification>()?.also { nf ->
@@ -609,20 +621,43 @@ class SystemUIHooker : YukiBaseHooker() {
}
afterHook {
if (firstArgs != null) instance<ImageView>().also {
/** 注册壁纸颜色监听 */
registerWallpaperColorChanged(it)
/** 注册广播 */
registerReceiver(it.context)
statusBarIconViews.add(it)
}
}
}
}
/** 注入状态栏通知图标容器实例 */
OplusNotificationIconAreaControllerClass.hook {
injectMember {
var isOldWay = false
method {
name = "updateIconsForLayout"
paramCount = 10
}.remedys {
method {
name = "updateIconsForLayout"
paramCount = 1
}.onFind { isOldWay = true }
}
afterHook {
if (isOldWay) {
notificationIconInstances.clear()
field { name = "mLastToShow" }.get(instance).list<View>()
.takeIf { it.isNotEmpty() }?.forEach { notificationIconInstances.add(it) }
} else notificationIconContainer = args(index = 1).cast()
}
}
}
/** 替换通知图标和样式 */
NotificationHeaderViewWrapperClass.hook {
injectMember {
method { name = "resolveHeaderViews" }
afterHook {
NotificationHeaderViewWrapperClass.clazz
.field { name = "mIcon" }.of<ImageView>(instance)?.apply {
.field { name = "mIcon" }.get(instance).cast<ImageView>()?.apply {
ExpandableNotificationRowClass.clazz
.method { name = "getEntry" }
.get(NotificationViewWrapperClass.clazz.field {
@@ -651,7 +686,7 @@ class SystemUIHooker : YukiBaseHooker() {
}
/** 记录实例 */
injectMember {
constructor { param(ContextClass, ViewClass, ExpandableNotificationRowClass.clazz) }
constructor { param(ContextClass, ViewClass, ExpandableNotificationRowClass) }
afterHook { notificationViewWrappers.add(instance) }
}
}
@@ -693,11 +728,16 @@ class SystemUIHooker : YukiBaseHooker() {
param(ContextClass, IntentClass)
}
afterHook {
if (isEnableHookColorNotifyIcon() && prefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_AUTO))
IconAdaptationTool.prepareAutoUpdateIconRule(
context = firstArgs()!!,
timeSet = prefs.get(DataConst.NOTIFY_ICON_FIX_AUTO_TIME)
)
firstArgs<Context>()?.also {
/** 注册广播 */
registerReceiver(it)
/** 注册定时监听 */
if (isEnableHookColorNotifyIcon() && prefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_AUTO))
IconAdaptationTool.prepareAutoUpdateIconRule(
context = it,
timeSet = prefs.get(DataConst.NOTIFY_ICON_FIX_AUTO_TIME)
)
}
}
}
}

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

@@ -140,8 +140,8 @@ val colorOSFullVersion get() = "${if (isRealmeUI) "RealmeUI " else ""}$colorOSVe
val colorOSVersion
get() = safeOf(default = "无法获取") {
(classOf(name = "com.oplus.os.OplusBuild").let {
it.field { name = "VERSIONS" }.ignoredError().of<Array<String>>()
?.get(it.method { name = "getOplusOSVERSION" }.ignoredError().get().callInt() - 1)
it.field { name = "VERSIONS" }.ignoredError().get().array<String>().takeIf { e -> e.isNotEmpty() }
?.get(it.method { name = "getOplusOSVERSION" }.ignoredError().get().int() - 1)
} ?: findPropString(
key = "ro.system.build.fingerprint", default = "无法获取"
).split("ssi:")[1].split("/")[0].trim()) + " ${Build.DISPLAY}"

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

@@ -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

@@ -5,8 +5,8 @@ plugins {
}
ext {
appVersionName = "1.5"
appVersionCode = 7
appVersionName = "1.53"
appVersionCode = 10
}
task clean(type: Delete) {