16 Commits
2.2 ... 2.35

10 changed files with 211 additions and 104 deletions

View File

@@ -2,7 +2,7 @@
[![Blank](https://img.shields.io/badge/build-passing-brightgreen)](https://github.com/fankes/MIUINativeNotifyIcon) [![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/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.35-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/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) [![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/static/v1?label=Telegram&message=交流讨论&color=0088cc)](https://t.me/XiaofangInternet)
@@ -85,6 +85,11 @@ ContrastColorUtil.getInstance().isGrayscaleIcon(drawable)
特地的把自己能有的小米手机刷成各种 MIUI 版本去为酷友做专项适配,我也是很累了,也希望你们能够多多支持,也能让 MIUI 做得更好。<br/><br/> 特地的把自己能有的小米手机刷成各种 MIUI 版本去为酷友做专项适配,我也是很累了,也希望你们能够多多支持,也能让 MIUI 做得更好。<br/><br/>
MIUI 再不重写,怕是永远会变成安卓之光。雷军,金凡!! 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) - [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.html)

View File

@@ -1,7 +1,7 @@
plugins { plugins {
id 'com.android.application' id 'com.android.application'
id 'kotlin-android' 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 { android {
@@ -44,11 +44,11 @@ android {
} }
} }
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_11
} }
kotlinOptions { kotlinOptions {
jvmTarget = '1.8' jvmTarget = '11'
} }
buildFeatures { buildFeatures {
viewBinding true viewBinding true
@@ -72,8 +72,8 @@ tasks.whenTaskAdded {
dependencies { dependencies {
compileOnly 'de.robv.android.xposed:api:82' compileOnly 'de.robv.android.xposed:api:82'
implementation 'com.highcapable.yukihookapi:api:1.0.67' implementation 'com.highcapable.yukihookapi:api:1.0.70'
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.67' ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.70'
implementation "com.github.topjohnwu.libsu:core:3.1.2" implementation "com.github.topjohnwu.libsu:core:3.1.2"
implementation 'androidx.annotation:annotation:1.3.0' implementation 'androidx.annotation:annotation:1.3.0'
implementation 'com.geyifeng.immersionbar:immersionbar:3.2.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_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}_202204041350"
/** 当前模块的版本校验标签 */ /** 当前模块的版本校验标签 */
const val MODULE_VERSION_VERIFY_TAG = "module_version_verify" const val MODULE_VERSION_VERIFY_TAG = "module_version_verify"

View File

@@ -23,6 +23,7 @@
package com.fankes.miui.notify.hook.entity package com.fankes.miui.notify.hook.entity
import android.app.NotificationManager import android.app.NotificationManager
import android.app.WallpaperManager
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
@@ -35,11 +36,13 @@ import android.graphics.drawable.Drawable
import android.graphics.drawable.Icon import android.graphics.drawable.Icon
import android.os.Build import android.os.Build
import android.service.notification.StatusBarNotification import android.service.notification.StatusBarNotification
import android.util.ArraySet
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.ViewOutlineProvider import android.view.ViewOutlineProvider
import android.widget.ImageView import android.widget.ImageView
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import androidx.core.view.children
import com.fankes.miui.notify.bean.IconDataBean import com.fankes.miui.notify.bean.IconDataBean
import com.fankes.miui.notify.const.Const import com.fankes.miui.notify.const.Const
import com.fankes.miui.notify.data.DataConst import com.fankes.miui.notify.data.DataConst
@@ -71,62 +74,70 @@ class SystemUIHooker : YukiBaseHooker() {
companion object { companion object {
/** MIUI 新版本存在的类 */ /** MIUI 新版本存在的类 */
private const val SystemUIApplicationClass = "${SYSTEMUI_PACKAGE_NAME}.SystemUIApplication" private const val SystemUIApplicationClass = "$SYSTEMUI_PACKAGE_NAME.SystemUIApplication"
/** MIUI 新版本存在的类 */ /** MIUI 新版本存在的类 */
private const val NotificationHeaderViewWrapperInjectorClass = 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 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" private const val PluginManagerImplClass = "$SYSTEMUI_PACKAGE_NAME.shared.plugins.PluginManagerImpl"
/** MIUI 存在的类 - 旧版本没有 */
private const val MiuiNotificationViewWrapperClass =
"${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.row.wrapper.MiuiNotificationViewWrapper"
/** 根据多个版本存在不同的包名相同的类 */ /** 根据多个版本存在不同的包名相同的类 */
private val MiuiClockClass = VariousClass( private val MiuiClockClass = VariousClass(
"${SYSTEMUI_PACKAGE_NAME}.statusbar.views.MiuiClock", "$SYSTEMUI_PACKAGE_NAME.statusbar.views.MiuiClock",
"${SYSTEMUI_PACKAGE_NAME}.statusbar.policy.MiuiClock" "$SYSTEMUI_PACKAGE_NAME.statusbar.policy.MiuiClock"
) )
/** 根据多个版本存在不同的包名相同的类 */ /** 根据多个版本存在不同的包名相同的类 */
private val ExpandableNotificationRowClass = VariousClass( private val ExpandableNotificationRowClass = VariousClass(
"${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.row.ExpandableNotificationRow", "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.row.ExpandableNotificationRow",
"${SYSTEMUI_PACKAGE_NAME}.statusbar.ExpandableNotificationRow" "$SYSTEMUI_PACKAGE_NAME.statusbar.ExpandableNotificationRow"
) )
/** 根据多个版本存在不同的包名相同的类 */ /** 根据多个版本存在不同的包名相同的类 */
private val NotificationViewWrapperClass = VariousClass( private val NotificationViewWrapperClass = VariousClass(
"${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.row.wrapper.NotificationViewWrapper", "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.row.wrapper.NotificationViewWrapper",
"${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.NotificationViewWrapper" "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationViewWrapper"
) )
/** 根据多个版本存在不同的包名相同的类 */ /** 根据多个版本存在不同的包名相同的类 */
private val NotificationHeaderViewWrapperClass = VariousClass( private val NotificationHeaderViewWrapperClass = VariousClass(
"${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.row.wrapper.NotificationHeaderViewWrapper", "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.row.wrapper.NotificationHeaderViewWrapper",
"${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.NotificationHeaderViewWrapper" "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationHeaderViewWrapper"
) )
/** 根据多个版本存在不同的包名相同的类 */ /** 根据多个版本存在不同的包名相同的类 */
private val NotificationUtilClass = VariousClass( private val NotificationUtilClass = VariousClass(
"${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.NotificationUtil", "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationUtil",
"${SYSTEMUI_PACKAGE_NAME}.miui.statusbar.notification.NotificationUtil" "$SYSTEMUI_PACKAGE_NAME.miui.statusbar.notification.NotificationUtil"
) )
/** 根据多个版本存在不同的包名相同的类 */ /** 根据多个版本存在不同的包名相同的类 */
private val ExpandedNotificationClass = VariousClass( private val ExpandedNotificationClass = VariousClass(
"${SYSTEMUI_PACKAGE_NAME}.statusbar.notification.ExpandedNotification", "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.ExpandedNotification",
"${SYSTEMUI_PACKAGE_NAME}.miui.statusbar.ExpandedNotification" "$SYSTEMUI_PACKAGE_NAME.miui.statusbar.ExpandedNotification"
) )
} }
@@ -139,14 +150,20 @@ class SystemUIHooker : YukiBaseHooker() {
/** 是否已经使用过缓存刷新功能 */ /** 是否已经使用过缓存刷新功能 */
private var isUsingCachingMethod = false private var isUsingCachingMethod = false
/** 缓存的状态栏小图标实例 */ /** 状态栏通知图标容器 */
private var statusBarIconViews = HashSet<ImageView>() private var notificationIconContainer: ViewGroup? = null
/** 缓存的通知小图标包装纸实例 */ /** 缓存的通知小图标包装纸实例 */
private var notificationViewWrappers = HashSet<Any>() private var notificationViewWrappers = ArraySet<Any>()
/** MIUI 样式下的缓存的通知小图标包装纸实例 */ /** MIUI 样式下的缓存的通知小图标包装纸实例 */
private var miuiNotificationViewWrappers = HashSet<Any>() private var miuiNotificationViewWrappers = ArraySet<Any>()
/** MIUI 样式下的缓存的通知小图标折叠通知实例 */
private var miuiNotificationChildrenContainers = ArraySet<ViewGroup>()
/** 仅监听一次主题壁纸颜色变化 */
private var isWallpaperColorListenerSetUp = false
/** 是否已经注册广播 */ /** 是否已经注册广播 */
private var isRegisterReceiver = false private var isRegisterReceiver = false
@@ -232,7 +249,7 @@ class SystemUIHooker : YukiBaseHooker() {
}.get(it.method { }.get(it.method {
name = "getInstance" name = "getInstance"
param(ContextClass) param(ContextClass)
}.get().invoke(context)).callBoolean(drawable) }.get().invoke(context)).boolean(drawable)
} }
} else BitmapCompatTool.isGrayscaleDrawable(drawable) } else BitmapCompatTool.isGrayscaleDrawable(drawable)
@@ -253,19 +270,10 @@ class SystemUIHooker : YukiBaseHooker() {
get() = safeOfFalse { get() = safeOfFalse {
NotificationUtilClass.clazz.hasMethod { NotificationUtilClass.clazz.hasMethod {
name = "ignoreStatusBarIconColor" name = "ignoreStatusBarIconColor"
param(ExpandedNotificationClass.clazz) param(ExpandedNotificationClass)
} }
} }
/**
* 获取当前通知栏的样式
*
* - ❗新版本可能不存在这个方法
* @return [Boolean]
*/
private val isShowMiuiStyle
get() = safeOfFalse { NotificationUtilClass.clazz.method { name = "showMiuiStyle" }.get().invoke() ?: false }
/** /**
* 处理为圆角图标 * 处理为圆角图标
* @return [Drawable] * @return [Drawable]
@@ -354,15 +362,28 @@ class SystemUIHooker : YukiBaseHooker() {
SystemUIApplicationClass.clazz.method { name = "getContext" }.ignoredError().get().invoke<Context>() SystemUIApplicationClass.clazz.method { name = "getContext" }.ignoredError().get().invoke<Context>()
} }
/**
* 注册主题壁纸改变颜色监听
*
* - 仅限在 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 { private fun refreshStatusBarIcons() = runInSafe {
StatusBarIconViewClass.clazz.field { name = "mNotification" }.also { result -> 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 -> 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) }
} }
} }
} }
@@ -378,6 +399,12 @@ class SystemUIHooker : YukiBaseHooker() {
MiuiNotificationViewWrapperClass.clazz.method { name = "handleViews" }.ignoredError().also { result -> MiuiNotificationViewWrapperClass.clazz.method { name = "handleViews" }.ignoredError().also { result ->
miuiNotificationViewWrappers.takeIf { it.isNotEmpty() }?.forEach { result.get(it).call() } miuiNotificationViewWrappers.takeIf { it.isNotEmpty() }?.forEach { result.get(it).call() }
} }
MiuiNotificationChildrenContainerClass.clazz.method {
name = "updateAppIcon"
param(BooleanType)
}.ignoredError().also { result ->
miuiNotificationChildrenContainers.takeIf { it.isNotEmpty() }?.forEach { result.get(it).call(true) }
}
} }
/** /**
@@ -498,7 +525,10 @@ class SystemUIHooker : YukiBaseHooker() {
setColorFilter(if (isUseAndroid12Style || customIconColor == 0) supportColor else customIconColor) setColorFilter(if (isUseAndroid12Style || customIconColor == 0) supportColor else customIconColor)
/** Android 12 设置图标外圈颜色 */ /** Android 12 设置图标外圈颜色 */
if (isUseAndroid12Style && customIconColor != 0) 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)) if (isUseAndroid12Style) setPadding(4.dp(context), 4.dp(context), 4.dp(context), 4.dp(context))
} else { } else {
@@ -511,8 +541,13 @@ class SystemUIHooker : YukiBaseHooker() {
/** 设置图标着色 */ /** 设置图标着色 */
setColorFilter(supportColor) setColorFilter(supportColor)
/** Android 12 设置图标外圈颜色 */ /** Android 12 设置图标外圈颜色 */
if (isUseAndroid12Style) background = (if (hasIconColor) iconColor else context.systemAccentColor).also {
DrawableBuilder().rounded().solidColor(if (hasIconColor) iconColor else context.systemAccentColor).build() 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)) if (isUseAndroid12Style) setPadding(4.dp(context), 4.dp(context), 4.dp(context), 4.dp(context))
} else iconImageView.apply { } else iconImageView.apply {
@@ -572,10 +607,10 @@ class SystemUIHooker : YukiBaseHooker() {
} }
/** /**
* 从 [NotificationViewWrapperClass] 中获取 [StatusBarNotification] * 从 [NotificationViewWrapperClass] 中获取 [ExpandableNotificationRowClass]
* @return [Pair] - ([Boolean] 通知是否展开,[StatusBarNotification] 通知实例) * @return [Pair] - ([Boolean] 通知是否展开,[Any] 通知 Row 实例)
*/ */
private fun Any.getSbnPair(): Pair<Boolean, StatusBarNotification?> { private fun Any.getRowPair(): Pair<Boolean, Any?> {
/** 通知是否展开 */ /** 通知是否展开 */
var isExpanded = false var isExpanded = false
@@ -583,16 +618,25 @@ class SystemUIHooker : YukiBaseHooker() {
* 从父类中得到 mRow 变量 - [ExpandableNotificationRowClass] * 从父类中得到 mRow 变量 - [ExpandableNotificationRowClass]
* 获取其中的得到通知方法 * 获取其中的得到通知方法
*/ */
val expandedNf = ExpandableNotificationRowClass.clazz val row = NotificationViewWrapperClass.clazz.field {
name = "mRow"
}.get(this).self?.also {
isExpanded = ExpandableNotificationRowClass.clazz.method {
name = "isExpanded"
returnType = BooleanType
}.get(it).boolean()
}
return Pair(isExpanded, row)
}
/**
* 从 [ExpandableNotificationRowClass] 中获取 [StatusBarNotification]
* @return [StatusBarNotification] or null
*/
private fun Any?.getSbn() =
ExpandableNotificationRowClass.clazz
.method { name = "getEntry" } .method { name = "getEntry" }
.get(NotificationViewWrapperClass.clazz.field { .get(this).call()?.let {
name = "mRow"
}.get(this).self?.also {
isExpanded = ExpandableNotificationRowClass.clazz.method {
name = "isExpanded"
returnType = BooleanType
}.get(it).callBoolean()
}).call()?.let {
it.javaClass.method { it.javaClass.method {
name = "getSbn" name = "getSbn"
}.get(it).invoke<StatusBarNotification>() }.get(it).invoke<StatusBarNotification>()
@@ -600,8 +644,6 @@ class SystemUIHooker : YukiBaseHooker() {
.method { name = "getStatusBarNotification" } .method { name = "getStatusBarNotification" }
.get(NotificationViewWrapperClass.clazz.field { name = "mRow" }.get(this).self) .get(NotificationViewWrapperClass.clazz.field { name = "mRow" }.get(this).self)
.invoke<StatusBarNotification>() .invoke<StatusBarNotification>()
return Pair(isExpanded, expandedNf)
}
/** 缓存图标数据 */ /** 缓存图标数据 */
private fun cachingIconDatas() { private fun cachingIconDatas() {
@@ -636,33 +678,29 @@ class SystemUIHooker : YukiBaseHooker() {
injectMember { injectMember {
method { method {
name = "shouldSubstituteSmallIcon" name = "shouldSubstituteSmallIcon"
param(ExpandedNotificationClass.clazz) param(ExpandedNotificationClass)
} }
/** replaceToFalse()
* MIUI 12 在非原生样式下 MIPUSH 的图标着色异常
* 所以判断是 MIUI 样式就停止 Hook 状态栏图标
*/
replaceAny { hasIgnoreStatusBarIconColor.not() && isShowMiuiStyle }
} }
/** 强制回写系统的状态栏图标样式为原生 */ /** 强制回写系统的状态栏图标样式为原生 */
injectMember { injectMember {
var isUseLegacy = false var isUseLegacy = false
method { method {
name = "getSmallIcon" name = "getSmallIcon"
param(ExpandedNotificationClass.clazz, IntType) param(ExpandedNotificationClass, IntType)
}.remedys { }.remedys {
method { method {
name = "getSmallIcon" name = "getSmallIcon"
param(ExpandedNotificationClass.clazz) param(ExpandedNotificationClass)
} }
method { method {
name = "getSmallIcon" name = "getSmallIcon"
param(ContextClass, ExpandedNotificationClass.clazz) param(ContextClass, ExpandedNotificationClass)
}.onFind { isUseLegacy = true } }.onFind { isUseLegacy = true }
} }
afterHook { afterHook {
(globalContext ?: firstArgs())?.also { context -> (globalContext ?: firstArgs())?.also { context ->
val expandedNf = args(if (isUseLegacy) 1 else 0).of<StatusBarNotification?>() val expandedNf = args(if (isUseLegacy) 1 else 0).cast<StatusBarNotification?>()
/** Hook 状态栏小图标 */ /** Hook 状态栏小图标 */
compatStatusIcon( compatStatusIcon(
context = context, context = context,
@@ -681,7 +719,7 @@ class SystemUIHooker : YukiBaseHooker() {
afterHook { afterHook {
instance<ImageView>().also { instance<ImageView>().also {
if (hasIgnoreStatusBarIconColor(it.context, field { name = "mNotification" } if (hasIgnoreStatusBarIconColor(it.context, field { name = "mNotification" }
.of<StatusBarNotification>(instance))) it.apply { .get(instance).cast<StatusBarNotification>())) it.apply {
alpha = 1f alpha = 1f
colorFilter = null colorFilter = null
} else it.apply { } else it.apply {
@@ -690,7 +728,7 @@ class SystemUIHooker : YukiBaseHooker() {
* 图标在任何场景下跟随状态栏其它图标保持半透明 * 图标在任何场景下跟随状态栏其它图标保持半透明
* MIUI 12 进行单独判断 * MIUI 12 进行单独判断
*/ */
field { name = "mCurrentSetColor" }.ofInt(instance).also { color -> field { name = "mCurrentSetColor" }.get(instance).int().also { color ->
if (hasIgnoreStatusBarIconColor) { if (hasIgnoreStatusBarIconColor) {
alpha = if (color.isWhite) 0.95f else 0.8f alpha = if (color.isWhite) 0.95f else 0.8f
setColorFilter(if (color.isWhite) color else Color.BLACK) setColorFilter(if (color.isWhite) color else Color.BLACK)
@@ -708,13 +746,15 @@ class SystemUIHooker : YukiBaseHooker() {
}.remedys { }.remedys {
method { method {
name = "setNotification" name = "setNotification"
param(ExpandedNotificationClass.clazz) param(ExpandedNotificationClass)
} }
} }
afterHook { afterHook {
if (firstArgs != null) instance<ImageView>().also { if (firstArgs != null) instance<ImageView>().also {
/** 注册壁纸颜色监听 */
registerWallpaperColorChanged(it)
/** 注册广播 */
registerReceiver(it.context) registerReceiver(it.context)
statusBarIconViews.add(it)
} }
} }
} }
@@ -724,6 +764,8 @@ class SystemUIHooker : YukiBaseHooker() {
injectMember { injectMember {
method { name = "calculateIconTranslations" } method { name = "calculateIconTranslations" }
afterHook { afterHook {
/** 缓存实例 */
notificationIconContainer = instance<ViewGroup>()
/** 修复部分开发版状态栏图标只能显示一个的问题 */ /** 修复部分开发版状态栏图标只能显示一个的问题 */
when (miuiIncrementalVersion.lowercase()) { when (miuiIncrementalVersion.lowercase()) {
"22.3.14", "22.3.15", "22.3.16", "v13.0.1.1.16.dev", "22.3.18" -> "22.3.14", "22.3.15", "22.3.16", "v13.0.1.1.16.dev", "22.3.18" ->
@@ -740,7 +782,7 @@ class SystemUIHooker : YukiBaseHooker() {
.get(instance).set(prefs.get(DataConst.HOOK_STATUS_ICON_COUNT) .get(instance).set(prefs.get(DataConst.HOOK_STATUS_ICON_COUNT)
.let { if (it in 0..100) it else 5 }) .let { if (it in 0..100) it else 5 })
} }
} }.by { NotificationIconContainerClass.clazz.hasField { name = "MAX_STATIC_ICONS" } }
/** 旧版方法 - 新版不存在 */ /** 旧版方法 - 新版不存在 */
injectMember { injectMember {
method { method {
@@ -757,7 +799,7 @@ class SystemUIHooker : YukiBaseHooker() {
} }
beforeHook { isShowNotificationIcons = firstArgs<Boolean>() ?: false } beforeHook { isShowNotificationIcons = firstArgs<Boolean>() ?: false }
}.ignoredNoSuchMemberFailure() }.ignoredNoSuchMemberFailure()
}.by { NotificationIconContainerClass.clazz.hasField { name = "MAX_STATIC_ICONS" } } }
/** 注入原生通知包装纸实例 */ /** 注入原生通知包装纸实例 */
NotificationHeaderViewWrapperClass.hook { NotificationHeaderViewWrapperClass.hook {
/** 修复下拉通知图标自动设置回 APP 图标的方法 */ /** 修复下拉通知图标自动设置回 APP 图标的方法 */
@@ -769,27 +811,30 @@ class SystemUIHooker : YukiBaseHooker() {
/** 获取小图标 */ /** 获取小图标 */
val iconImageView = val iconImageView =
NotificationHeaderViewWrapperClass.clazz 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] */ /** 获取 [StatusBarNotification] */
val sbnPair = instance.getSbnPair() val expandedNf = rowPair.second.getSbn()
/** 通知是否展开 */ /** 通知是否展开 */
var isExpanded = sbnPair.first var isExpanded = rowPair.first
/** 获取优先级 */ /** 获取优先级 */
val importance = val importance =
(iconImageView.context.getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager?) (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 if (importance != 1) isExpanded = true
/** 执行 Hook */ /** 执行 Hook */
compatNotifyIcon(iconImageView.context, sbnPair.second, iconImageView, isExpanded) compatNotifyIcon(iconImageView.context, expandedNf, iconImageView, isExpanded)
} }
} }
/** 记录实例 */ /** 记录实例 */
injectMember { injectMember {
constructor { param(ContextClass, ViewClass, ExpandableNotificationRowClass.clazz) } constructor { param(ContextClass, ViewClass, ExpandableNotificationRowClass) }
afterHook { notificationViewWrappers.add(instance) } afterHook { notificationViewWrappers.add(instance) }
} }
} }
@@ -799,27 +844,55 @@ class SystemUIHooker : YukiBaseHooker() {
injectMember { injectMember {
method { name = "handleAppIcon" } method { name = "handleAppIcon" }
replaceUnit { replaceUnit {
field { name = "mAppIcon" }.of<ImageView>(instance)?.apply { field { name = "mAppIcon" }.get(instance).cast<ImageView>()?.apply {
compatNotifyIcon(context, instance.getSbnPair().second, iconImageView = this, isUseAndroid12Style = true) compatNotifyIcon(
context = context,
expandedNf = instance.getRowPair().second.getSbn(),
iconImageView = this,
isUseAndroid12Style = true
)
} }
} }
} }
/** 记录实例 */ /** 记录实例 */
injectMember { injectMember {
constructor { param(ContextClass, ViewClass, ExpandableNotificationRowClass.clazz) } constructor { param(ContextClass, ViewClass, ExpandableNotificationRowClass) }
afterHook { miuiNotificationViewWrappers.add(instance) } afterHook { miuiNotificationViewWrappers.add(instance) }
} }
}.ignoredHookClassNotFoundFailure() }.ignoredHookClassNotFoundFailure()
/** 修改 MIUI 风格通知栏的通知图标 - 折叠通知 */
MiuiNotificationChildrenContainerClass.hook {
/** 替换通知小图标 */
injectMember {
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)
}
}
}
/** 记录实例 */
injectMember {
constructor { param(ContextClass, AttributeSetClass) }
afterHook { miuiNotificationChildrenContainers.add(instance()) }
}
}.ignoredHookClassNotFoundFailure()
/** 干掉下拉通知图标自动设置回 APP 图标的方法 */ /** 干掉下拉通知图标自动设置回 APP 图标的方法 */
NotificationHeaderViewWrapperInjectorClass.hook { NotificationHeaderViewWrapperInjectorClass.hook {
injectMember { injectMember {
method { method {
name = "setAppIcon" name = "setAppIcon"
param(ContextClass, ImageViewClass, ExpandedNotificationClass.clazz) param(ContextClass, ImageViewClass, ExpandedNotificationClass)
}.remedys { }.remedys {
method { method {
name = "setAppIcon" name = "setAppIcon"
param(ImageViewClass, ExpandedNotificationClass.clazz) param(ImageViewClass, ExpandedNotificationClass)
} }
} }
intercept() intercept()
@@ -827,7 +900,7 @@ class SystemUIHooker : YukiBaseHooker() {
injectMember { injectMember {
method { method {
name = "resetIconBgAndPaddings" name = "resetIconBgAndPaddings"
param(ImageViewClass, ExpandedNotificationClass.clazz) param(ImageViewClass, ExpandedNotificationClass)
} }
intercept() intercept()
}.ignoredNoSuchMemberFailure() }.ignoredNoSuchMemberFailure()
@@ -867,11 +940,16 @@ class SystemUIHooker : YukiBaseHooker() {
injectMember { injectMember {
method { name = "updateTime" } method { name = "updateTime" }
afterHook { afterHook {
if (isEnableHookColorNotifyIcon() && prefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_AUTO)) instance<View>().context.also {
IconAdaptationTool.prepareAutoUpdateIconRule( /** 注册广播 */
context = instance<View>().context, registerReceiver(it)
timeSet = prefs.get(DataConst.NOTIFY_ICON_FIX_AUTO_TIME) /** 注册定时监听 */
) if (isEnableHookColorNotifyIcon() && prefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_AUTO))
IconAdaptationTool.prepareAutoUpdateIconRule(
context = it,
timeSet = prefs.get(DataConst.NOTIFY_ICON_FIX_AUTO_TIME)
)
}
} }
} }
}.ignoredHookClassNotFoundFailure() }.ignoredHookClassNotFoundFailure()

View File

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

View File

@@ -39,7 +39,7 @@ import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.viewbinding.ViewBinding import androidx.viewbinding.ViewBinding
import com.google.android.material.dialog.MaterialAlertDialogBuilder 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.factory.method
import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass 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 // 对话框实例 private var dialogInstance: Dialog? = null // 对话框实例
@DoNotUseField @CauseProblemsApi
var customLayoutView: View? = null // 自定义布局 var customLayoutView: View? = null // 自定义布局
/** /**

View File

@@ -305,7 +305,20 @@ val Context.systemAccentColor
*/ */
val Context.wallpaperColor val Context.wallpaperColor
get() = safeOfNan { 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)
} }
/** /**

View File

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

View File

@@ -9,6 +9,17 @@
android:paddingRight="15dp" android:paddingRight="15dp"
tools:ignore="HardcodedText"> 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 <com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">

View File

@@ -5,8 +5,8 @@ plugins {
} }
ext { ext {
appVersionName = "2.2" appVersionName = "2.35"
appVersionCode = 27 appVersionCode = 29
} }
task clean(type: Delete) { task clean(type: Delete) {