27 Commits
2.9 ... 2.101

Author SHA1 Message Date
4703d339b7 Update version to 2.101 2023-05-14 19:16:05 +08:00
76b1cc2f0b Fix notification icon problem in MIUI 14 DEV version in SystemUIHooker 2023-05-14 15:51:36 +08:00
62ec1d16ae Update version to 2.100 2023-04-25 06:40:55 +08:00
7db010c9a1 Modify merge to YukiHookAPI new usage 2023-04-25 06:26:05 +08:00
e6fa34d7fd Update YukiHookAPI 2023-04-25 06:25:55 +08:00
d4661abb71 Update version to 2.99 2023-04-22 22:37:11 +08:00
744d028160 Modify remove prefs cache function and disable prefs cache 2023-04-22 22:32:16 +08:00
3f3a92f192 Update version to 2.98 2023-04-21 02:21:55 +08:00
49f18ef8c3 Added enable or disable prefs cache function 2023-04-21 02:15:08 +08:00
73173cd7ab Update YukiHookAPI 2023-04-21 01:29:06 +08:00
c181530ad7 Update version to 2.97 2023-04-18 01:09:05 +08:00
883325dc2f Added new GitHub proxy url 2023-04-18 00:31:55 +08:00
6fe1f0572c Added new module version update notification function 2023-04-17 23:46:35 +08:00
be8f558bf5 Added notification icon force system color function 2023-04-17 22:42:35 +08:00
175263c9aa Modify merge to YukiHookAPI new usage 2023-04-17 06:30:55 +08:00
f95fe45ce3 Update YukiHookAPI 2023-04-17 06:30:35 +08:00
42b0fa69b7 Modify merge contents of build.gradle into constant definitions 2023-04-15 23:16:35 +08:00
d0a9554a28 Update Gradle & Kotlin
- Update Kotlin version to 1.8.20
- Update Gradle version to 8.0.2
- Update Gradle dependencies
2023-04-08 00:08:36 +08:00
c500bdad43 Modify support monet launcher icon in ic_launcher 2023-02-25 21:27:55 +08:00
9bded26604 Update version to 2.95 2023-02-07 06:37:05 +08:00
c687c755f2 Fix some MIUI 12 system's notification icons color unusual problem in SystemUIHooker 2023-02-07 06:27:05 +08:00
b9e1d1abe7 Modify change wallpaperColor function's return value that cannot obtain return default color in FunctionFactory 2023-02-07 06:23:15 +08:00
27cfcbada6 Fix "GitHub" spelling in all files 2023-02-07 05:25:35 +08:00
f0c6dabf76 Modify replace to new placeholder notification icon in SystemUIHooker 2023-02-07 05:21:05 +08:00
208862bf62 Modify remove grayscale notification icons caching because some system has bugs in SystemUIHooker 2023-02-07 01:01:51 +08:00
ee948f5327 Fix "onDarkChanged" method params not correct on MIUI 12、12.5、13 based on Android 11 in SystemUIHooker 2023-02-07 00:50:55 +08:00
d62d0f99a2 Fix some function descriptions in MainActivity, activity_main 2023-02-06 22:32:15 +08:00
23 changed files with 406 additions and 179 deletions

View File

@@ -0,0 +1,6 @@
{
"keyAlias": "public",
"keyPassword": "123456",
"storeFileName": "universal.p12",
"storePassword": "123456"
}

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.9-green)](https://github.com/fankes/MIUINativeNotifyIcon/releases) [![Blank](https://img.shields.io/badge/version-v2.101-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/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/XiaofangInternet) [![Telegram](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/XiaofangInternet)
@@ -54,7 +54,7 @@ Fix the native notification bar icon function abandoned by the MIUI development
- [Automatic Build on Commit](https://github.com/fankes/MIUINativeNotifyIcon/actions/workflows/commit_ci.yml) - [Automatic Build on Commit](https://github.com/fankes/MIUINativeNotifyIcon/actions/workflows/commit_ci.yml)
上述更新为代码 `commit` 后自动触发,具体更新内容可点击上方的文字前往 **Github Actions** 进行查看,本更新由开源的流程自动编译发布,**不保证其稳定性**,所发布的版本**仅供测试**,且不会特殊说明甚至可能会变更版本号或保持与当前稳定版相同的版本号。 上述更新为代码 `commit` 后自动触发,具体更新内容可点击上方的文字前往 **GitHub Actions** 进行查看,本更新由开源的流程自动编译发布,**不保证其稳定性**,所发布的版本**仅供测试**,且不会特殊说明甚至可能会变更版本号或保持与当前稳定版相同的版本号。
- [Release](https://github.com/fankes/MIUINativeNotifyIcon/releases) - [Release](https://github.com/fankes/MIUINativeNotifyIcon/releases)
- [Xposed-Modules-Repo](https://github.com/Xposed-Modules-Repo/com.fankes.miui.notify/releases) - [Xposed-Modules-Repo](https://github.com/Xposed-Modules-Repo/com.fankes.miui.notify/releases)

View File

@@ -1,39 +1,51 @@
import groovy.json.JsonSlurper
plugins { plugins {
id 'com.android.application' id 'com.android.application'
id 'kotlin-android' id 'org.jetbrains.kotlin.android'
id 'com.google.devtools.ksp' version '1.7.22-1.0.8' id 'com.google.devtools.ksp'
} }
android { android {
compileSdk 33
signingConfigs { signingConfigs {
debug { universal {
storeFile file('../keystore/public') def dirPath = rootProject.ext.app.signingConfigs.secretConfigsDirPath
storePassword '123456' def fileName = rootProject.ext.app.signingConfigs.secretConfigsFileName
keyAlias 'public' def configs = new JsonSlurper().parse(file("${dirPath}/${fileName}"))
keyPassword '123456' keyAlias configs.keyAlias
keyPassword configs.keyPassword
storeFile file("${dirPath}/${configs.storeFileName}")
storePassword configs.storePassword
v1SigningEnabled true v1SigningEnabled true
v2SigningEnabled true v2SigningEnabled true
} }
} }
defaultConfig { namespace 'com.fankes.miui.notify'
applicationId "com.fankes.miui.notify" compileSdk rootProject.ext.android.compileSdk
minSdk 28
targetSdk 33
versionCode rootProject.ext.appVersionCode
versionName rootProject.ext.appVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" defaultConfig {
applicationId 'com.fankes.miui.notify'
minSdk rootProject.ext.android.minSdk
targetSdk rootProject.ext.android.targetSdk
versionCode rootProject.ext.app.versionCode
versionName rootProject.ext.app.versionName
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
} }
buildTypes { buildTypes {
debug {
minifyEnabled false
signingConfig signingConfigs.universal
}
release { release {
minifyEnabled rootProject.ext.enableR8 minifyEnabled true
shrinkResources rootProject.ext.enableR8 shrinkResources true
zipAlignEnabled rootProject.ext.enableR8 zipAlignEnabled true
signingConfig signingConfigs.debug signingConfig signingConfigs.universal
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
} }
@@ -60,14 +72,14 @@ android {
dependencies { dependencies {
compileOnly 'de.robv.android.xposed:api:82' compileOnly 'de.robv.android.xposed:api:82'
implementation 'com.highcapable.yukihookapi:api:1.1.8' implementation 'com.highcapable.yukihookapi:api:1.1.11'
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.1.8' ksp 'com.highcapable.yukihookapi:ksp-xposed:1.1.11'
implementation 'com.github.duanhong169:drawabletoolbox:1.0.7' implementation 'com.github.duanhong169:drawabletoolbox:1.0.7'
implementation "com.github.topjohnwu.libsu:core:3.1.2" implementation "com.github.topjohnwu.libsu:core:5.0.4"
implementation 'androidx.annotation:annotation:1.5.0' implementation 'androidx.annotation:annotation:1.6.0'
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.7' implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.7'
implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.core:core-ktx:1.10.0'
implementation 'androidx.appcompat:appcompat:1.6.0' implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.8.0' implementation 'com.google.android.material:material:1.8.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'

View File

@@ -36,10 +36,13 @@ object PackageName {
*/ */
object IconRuleSourceSyncType { object IconRuleSourceSyncType {
/** Github Raw (代理) */ /** GitHub Raw (代理 - GitHub Proxy) */
const val GITHUB_RAW_PROXY = 1000 const val GITHUB_RAW_PROXY_1 = 500
/** Github Raw (直连) */ /** GitHub Raw (代理 - 7ED Services) */
const val GITHUB_RAW_PROXY_2 = 1000
/** GitHub Raw (直连) */
const val GITHUB_RAW_DIRECT = 2000 const val GITHUB_RAW_DIRECT = 2000
/** 自定义地址 */ /** 自定义地址 */

View File

@@ -26,7 +26,7 @@ package com.fankes.miui.notify.data
import android.content.Context import android.content.Context
import com.fankes.miui.notify.const.IconRuleSourceSyncType import com.fankes.miui.notify.const.IconRuleSourceSyncType
import com.highcapable.yukihookapi.hook.factory.modulePrefs import com.highcapable.yukihookapi.hook.factory.prefs
import com.highcapable.yukihookapi.hook.log.loggerW import com.highcapable.yukihookapi.hook.log.loggerW
import com.highcapable.yukihookapi.hook.param.PackageParam import com.highcapable.yukihookapi.hook.param.PackageParam
import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData
@@ -60,6 +60,9 @@ object ConfigData {
/** 通知栏中的通知图标圆角程度 */ /** 通知栏中的通知图标圆角程度 */
val NOTIFY_ICON_CORNER_SIZE = PrefsData("_notify_icon_corner", 15) val NOTIFY_ICON_CORNER_SIZE = PrefsData("_notify_icon_corner", 15)
/** 强制通知栏中的通知图标使用系统着色 */
val ENABLE_NOTIFY_ICON_FORCE_SYSTEM_COLOR = PrefsData("_notify_icon_force_system_color", false)
/** 强制通知栏中的通知图标为 APP 图标 */ /** 强制通知栏中的通知图标为 APP 图标 */
val ENABLE_NOTIFY_ICON_FORCE_APP_ICON = PrefsData("_notify_icon_force_app_icon", false) val ENABLE_NOTIFY_ICON_FORCE_APP_ICON = PrefsData("_notify_icon_force_app_icon", false)
@@ -82,7 +85,7 @@ object ConfigData {
val NOTIFY_ICONS_DATA = PrefsData("_notify_icon_datas", "") val NOTIFY_ICONS_DATA = PrefsData("_notify_icon_datas", "")
/** 通知图标优化名单同步方式 */ /** 通知图标优化名单同步方式 */
val ICON_RULE_SOURCE_SYNC_TYPE = PrefsData("_rule_source_sync_way", IconRuleSourceSyncType.GITHUB_RAW_PROXY) val ICON_RULE_SOURCE_SYNC_TYPE = PrefsData("_rule_source_sync_way", IconRuleSourceSyncType.GITHUB_RAW_PROXY_1)
/** 通知图标优化名单同步地址 */ /** 通知图标优化名单同步地址 */
val ICON_RULE_SOURCE_SYNC_CUSTOM_URL = PrefsData("_rule_source_sync_way_custom_url", "") val ICON_RULE_SOURCE_SYNC_CUSTOM_URL = PrefsData("_rule_source_sync_way_custom_url", "")
@@ -111,7 +114,7 @@ object ConfigData {
* @return [String] * @return [String]
*/ */
private fun getString(data: PrefsData<String>) = when (instance) { private fun getString(data: PrefsData<String>) = when (instance) {
is Context -> (instance as Context).modulePrefs.get(data) is Context -> (instance as Context).prefs().get(data)
is PackageParam -> (instance as PackageParam).prefs.get(data) is PackageParam -> (instance as PackageParam).prefs.get(data)
else -> error("Unknown type for get prefs data") else -> error("Unknown type for get prefs data")
} }
@@ -123,7 +126,7 @@ object ConfigData {
*/ */
private fun putString(data: PrefsData<String>, value: String) { private fun putString(data: PrefsData<String>, value: String) {
when (instance) { when (instance) {
is Context -> (instance as Context).modulePrefs.put(data, value) is Context -> (instance as Context).prefs().edit { put(data, value) }
is PackageParam -> loggerW(msg = "Not support for this method") is PackageParam -> loggerW(msg = "Not support for this method")
else -> error("Unknown type for put prefs data") else -> error("Unknown type for put prefs data")
} }
@@ -135,7 +138,7 @@ object ConfigData {
* @return [Int] * @return [Int]
*/ */
internal fun getInt(data: PrefsData<Int>) = when (instance) { internal fun getInt(data: PrefsData<Int>) = when (instance) {
is Context -> (instance as Context).modulePrefs.get(data) is Context -> (instance as Context).prefs().get(data)
is PackageParam -> (instance as PackageParam).prefs.get(data) is PackageParam -> (instance as PackageParam).prefs.get(data)
else -> error("Unknown type for get prefs data") else -> error("Unknown type for get prefs data")
} }
@@ -147,7 +150,7 @@ object ConfigData {
*/ */
internal fun putInt(data: PrefsData<Int>, value: Int) { internal fun putInt(data: PrefsData<Int>, value: Int) {
when (instance) { when (instance) {
is Context -> (instance as Context).modulePrefs.put(data, value) is Context -> (instance as Context).prefs().edit { put(data, value) }
is PackageParam -> loggerW(msg = "Not support for this method") is PackageParam -> loggerW(msg = "Not support for this method")
else -> error("Unknown type for put prefs data") else -> error("Unknown type for put prefs data")
} }
@@ -159,7 +162,7 @@ object ConfigData {
* @return [Boolean] * @return [Boolean]
*/ */
internal fun getBoolean(data: PrefsData<Boolean>) = when (instance) { internal fun getBoolean(data: PrefsData<Boolean>) = when (instance) {
is Context -> (instance as Context).modulePrefs.get(data) is Context -> (instance as Context).prefs().get(data)
is PackageParam -> (instance as PackageParam).prefs.get(data) is PackageParam -> (instance as PackageParam).prefs.get(data)
else -> error("Unknown type for get prefs data") else -> error("Unknown type for get prefs data")
} }
@@ -171,7 +174,7 @@ object ConfigData {
*/ */
internal fun putBoolean(data: PrefsData<Boolean>, value: Boolean) { internal fun putBoolean(data: PrefsData<Boolean>, value: Boolean) {
when (instance) { when (instance) {
is Context -> (instance as Context).modulePrefs.put(data, value) is Context -> (instance as Context).prefs().edit { put(data, value) }
is PackageParam -> loggerW(msg = "Not support for this method") is PackageParam -> loggerW(msg = "Not support for this method")
else -> error("Unknown type for put prefs data") else -> error("Unknown type for put prefs data")
} }
@@ -257,6 +260,16 @@ object ConfigData {
putInt(NOTIFY_ICON_CORNER_SIZE, value) putInt(NOTIFY_ICON_CORNER_SIZE, value)
} }
/**
* 是否强制通知栏中的通知图标使用系统着色
* @return [Boolean]
*/
var isEnableNotifyIconForceSystemColor
get() = getBoolean(ENABLE_NOTIFY_ICON_FORCE_SYSTEM_COLOR)
set(value) {
putBoolean(ENABLE_NOTIFY_ICON_FORCE_SYSTEM_COLOR, value)
}
/** /**
* 是否强制通知栏中的通知图标为 APP 图标 * 是否强制通知栏中的通知图标为 APP 图标
* @return [Boolean] * @return [Boolean]

View File

@@ -54,6 +54,7 @@ import com.fankes.miui.notify.params.IconPackParams
import com.fankes.miui.notify.params.factory.isAppNotifyHookAllOf import com.fankes.miui.notify.params.factory.isAppNotifyHookAllOf
import com.fankes.miui.notify.params.factory.isAppNotifyHookOf import com.fankes.miui.notify.params.factory.isAppNotifyHookOf
import com.fankes.miui.notify.utils.factory.* import com.fankes.miui.notify.utils.factory.*
import com.fankes.miui.notify.utils.tool.ActivationPromptTool
import com.fankes.miui.notify.utils.tool.BitmapCompatTool import com.fankes.miui.notify.utils.tool.BitmapCompatTool
import com.fankes.miui.notify.utils.tool.IconAdaptationTool import com.fankes.miui.notify.utils.tool.IconAdaptationTool
import com.fankes.miui.notify.utils.tool.SystemUITool import com.fankes.miui.notify.utils.tool.SystemUITool
@@ -63,9 +64,7 @@ import com.highcapable.yukihookapi.hook.factory.*
import com.highcapable.yukihookapi.hook.log.loggerD import com.highcapable.yukihookapi.hook.log.loggerD
import com.highcapable.yukihookapi.hook.log.loggerW import com.highcapable.yukihookapi.hook.log.loggerW
import com.highcapable.yukihookapi.hook.type.android.* import com.highcapable.yukihookapi.hook.type.android.*
import com.highcapable.yukihookapi.hook.type.defined.VagueType
import com.highcapable.yukihookapi.hook.type.java.BooleanType import com.highcapable.yukihookapi.hook.type.java.BooleanType
import com.highcapable.yukihookapi.hook.type.java.FloatType
import com.highcapable.yukihookapi.hook.type.java.IntType import com.highcapable.yukihookapi.hook.type.java.IntType
import top.defaults.drawabletoolbox.DrawableBuilder import top.defaults.drawabletoolbox.DrawableBuilder
@@ -142,9 +141,6 @@ object SystemUIHooker : YukiBaseHooker() {
/** 缓存的通知图标优化数组 */ /** 缓存的通知图标优化数组 */
private var iconDatas = ArrayList<IconDataBean>() private var iconDatas = ArrayList<IconDataBean>()
/** 已缓存的灰度图标 (单色图标) 判断结果数组 */
private val grayscaleIconResults = HashMap<String, Boolean>()
/** 当前是否处于深色图标模式 - 跟随 Hook 保存 */ /** 当前是否处于深色图标模式 - 跟随 Hook 保存 */
private var isDarkIconMode = false private var isDarkIconMode = false
@@ -251,22 +247,15 @@ object SystemUIHooker : YukiBaseHooker() {
} }
/** /**
* 判断是否为灰度图标 (单色图标) * - 这个是修复彩色图标的关键核心代码判断
*
* 判断是否为灰度图标 - 反射执行系统方法
* @param context 实例 * @param context 实例
* @param drawable 要判断的图标 * @param drawable 要判断的图标
* @param instance 用于标识缓存的实例
* @return [Boolean] * @return [Boolean]
*/ */
private fun isGrayscaleIcon(context: Context, drawable: Drawable, instance: Any): Boolean { private fun isGrayscaleIcon(context: Context, drawable: Drawable) =
/** 从缓存中读取的结果 */ if (ConfigData.isEnableColorIconCompat.not()) safeOfFalse {
val cachedResult = when (instance) {
is StatusBarNotification -> grayscaleIconResults[instance.notification.toString()]
is Notification -> grayscaleIconResults[instance.toString()]
else -> null
}
/** 当前实时获取的结果 */
val currentResult = if (ConfigData.isEnableColorIconCompat.not()) safeOfFalse {
ContrastColorUtilClass.toClass().let { ContrastColorUtilClass.toClass().let {
it.method { it.method {
name = "isGrayscaleIcon" name = "isGrayscaleIcon"
@@ -277,13 +266,6 @@ object SystemUIHooker : YukiBaseHooker() {
}.get().invoke(context)).boolean(drawable) }.get().invoke(context)).boolean(drawable)
} }
} else BitmapCompatTool.isGrayscaleDrawable(drawable) } else BitmapCompatTool.isGrayscaleDrawable(drawable)
return cachedResult ?: currentResult.also {
when (instance) {
is StatusBarNotification -> grayscaleIconResults[instance.notification.toString()] = it
is Notification -> grayscaleIconResults[instance.toString()] = it
}
}
}
/** /**
* 处理为圆角图标 * 处理为圆角图标
@@ -362,7 +344,7 @@ object SystemUIHooker : YukiBaseHooker() {
} }
} }
if (isGrayscaleIcon.not() && ConfigData.isEnableNotifyIconFixPlaceholder) if (isGrayscaleIcon.not() && ConfigData.isEnableNotifyIconFixPlaceholder)
customPair = Triple(context.resources.drawableOf(R.drawable.ic_unsupported), 0, true) customPair = Triple(context.resources.drawableOf(R.drawable.ic_message), 0, true)
} }
return customPair ?: Triple(null, 0, false) return customPair ?: Triple(null, 0, false)
} }
@@ -379,7 +361,7 @@ object SystemUIHooker : YukiBaseHooker() {
private fun compatStatusIcon(context: Context, nf: StatusBarNotification?, iconDrawable: Drawable?) = nf?.let { notifyInstance -> private fun compatStatusIcon(context: Context, nf: StatusBarNotification?, iconDrawable: Drawable?) = nf?.let { notifyInstance ->
if (iconDrawable == null) return@let Pair(null, false) if (iconDrawable == null) return@let Pair(null, false)
/** 判断是否不是灰度图标 */ /** 判断是否不是灰度图标 */
val isGrayscaleIcon = notifyInstance.isXmsf.not() && isGrayscaleIcon(context, iconDrawable, notifyInstance) val isGrayscaleIcon = notifyInstance.isXmsf.not() && isGrayscaleIcon(context, iconDrawable)
/** 目标彩色通知 APP 图标 */ /** 目标彩色通知 APP 图标 */
val customTriple = compatCustomIcon(context, isGrayscaleIcon, notifyInstance.nfPkgName) val customTriple = compatCustomIcon(context, isGrayscaleIcon, notifyInstance.nfPkgName)
@@ -457,10 +439,10 @@ object SystemUIHooker : YukiBaseHooker() {
val iconColor = notifyInstance.notification.color val iconColor = notifyInstance.notification.color
/** 是否有通知栏图标颜色 */ /** 是否有通知栏图标颜色 */
val hasIconColor = iconColor != 0 val hasIconColor = iconColor != 0 && ConfigData.isEnableNotifyIconForceSystemColor.not()
/** 通知图标适配颜色 */ /** 通知图标适配颜色 */
val supportColor = iconColor.let { val supportColor = (iconColor.takeIf { ConfigData.isEnableNotifyIconForceSystemColor.not() } ?: 0).let {
when { when {
isUseMaterial3Style -> newStyle isUseMaterial3Style -> newStyle
it == 0 || isExpanded.not() -> oldStyle it == 0 || isExpanded.not() -> oldStyle
@@ -473,7 +455,7 @@ object SystemUIHooker : YukiBaseHooker() {
?: return@let loggerW(msg = "compatNotifyIcon got null smallIcon") ?: return@let loggerW(msg = "compatNotifyIcon got null smallIcon")
/** 判断图标风格 */ /** 判断图标风格 */
val isGrayscaleIcon = notifyInstance.isXmsf.not() && isGrayscaleIcon(context, iconDrawable, notifyInstance) val isGrayscaleIcon = notifyInstance.isXmsf.not() && isGrayscaleIcon(context, iconDrawable)
/** 自定义默认小图标 */ /** 自定义默认小图标 */
var customIcon: Drawable? = null var customIcon: Drawable? = null
@@ -485,7 +467,8 @@ object SystemUIHooker : YukiBaseHooker() {
if (it.third) return@also if (it.third) return@also
customIcon = it.first customIcon = it.first
customIconColor = if (isUseMaterial3Style || isExpanded) customIconColor = if (isUseMaterial3Style || isExpanded)
(it.second.takeIf { e -> e != 0 } ?: (if (isUseMaterial3Style) context.systemAccentColor else 0)) else 0 (it.second.takeIf { e -> e != 0 && ConfigData.isEnableNotifyIconForceSystemColor.not() }
?: (if (isUseMaterial3Style) context.systemAccentColor else 0)) else 0
} }
/** 打印日志 */ /** 打印日志 */
loggerDebug(tag = "Notification Panel Icon", context, notifyInstance, isCustom = customIcon != null, isGrayscaleIcon) loggerDebug(tag = "Notification Panel Icon", context, notifyInstance, isCustom = customIcon != null, isGrayscaleIcon)
@@ -553,7 +536,7 @@ object SystemUIHooker : YukiBaseHooker() {
?: return loggerW(msg = "isGrayscaleIcon got null smallIcon").let { false } ?: return loggerW(msg = "isGrayscaleIcon got null smallIcon").let { false }
/** 判断是否不是灰度图标 */ /** 判断是否不是灰度图标 */
val isGrayscaleIcon = notifyInstance.isXmsf.not() && isGrayscaleIcon(context, iconDrawable, notifyInstance) val isGrayscaleIcon = notifyInstance.isXmsf.not() && isGrayscaleIcon(context, iconDrawable)
/** 获取目标修复彩色图标的 APP */ /** 获取目标修复彩色图标的 APP */
val isTargetFixApp = compatCustomIcon(context, isGrayscaleIcon, notifyInstance.nfPkgName).first != null val isTargetFixApp = compatCustomIcon(context, isGrayscaleIcon, notifyInstance.nfPkgName).first != null
@@ -601,6 +584,37 @@ object SystemUIHooker : YukiBaseHooker() {
} }
} }
/**
* Hook 原生通知包装纸实例内容
* @param wrapper 通知包装纸实例
*/
private fun hookNotificationViewWrapper(wrapper: Any) {
/** 忽略较旧版本 - 在没有 MIUI 通知栏样式的时候可能出现奇怪的问题 */
if (isNotHasAbsoluteMiuiStyle && isShowMiuiStyle) return
/** 获取小图标 */
val iconImageView = NotificationHeaderViewWrapperClass.toClassOrNull()
?.field { name = "mIcon" }?.get(wrapper)?.cast<ImageView>() ?: return
/** 获取 [ExpandableNotificationRowClass] */
val rowPair = wrapper.getRowPair()
/** 获取 [StatusBarNotification] */
val expandedNf = rowPair.second.getSbn()
/** 通知是否展开 */
var isExpanded = rowPair.first
/** 获取优先级 */
val importance =
(iconImageView.context.getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager?)
?.getNotificationChannel(expandedNf?.notification?.channelId)?.importance ?: 0
/** 非最小化优先级的通知全部设置为展开状态 */
if (importance != 1) isExpanded = true
/** 执行 Hook */
compatNotifyIcon(iconImageView.context, expandedNf, iconImageView, isExpanded)
}
/** /**
* 从 [NotificationViewWrapperClass] 中获取 [ExpandableNotificationRowClass] * 从 [NotificationViewWrapperClass] 中获取 [ExpandableNotificationRowClass]
* @return [Pair] - ([Boolean] 通知是否展开,[Any] 通知 Row 实例) * @return [Pair] - ([Boolean] 通知是否展开,[Any] 通知 Row 实例)
@@ -680,11 +694,12 @@ object SystemUIHooker : YukiBaseHooker() {
addAction(Intent.ACTION_PACKAGE_REPLACED) addAction(Intent.ACTION_PACKAGE_REPLACED)
addAction(Intent.ACTION_PACKAGE_REMOVED) addAction(Intent.ACTION_PACKAGE_REMOVED)
}) { context, intent -> }) { context, intent ->
intent.data?.schemeSpecificPart?.also { packageName ->
if (intent.action.equals(Intent.ACTION_PACKAGE_REPLACED)) ActivationPromptTool.prompt(context, packageName)
if (intent.action.equals(Intent.ACTION_PACKAGE_REPLACED).not() && if (intent.action.equals(Intent.ACTION_PACKAGE_REPLACED).not() &&
intent.getBooleanExtra(Intent.EXTRA_REPLACING, false) intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)
) return@registerReceiver ) return@registerReceiver
if (ConfigData.isEnableNotifyIconFix && ConfigData.isEnableNotifyIconFixNotify) if (ConfigData.isEnableNotifyIconFix && ConfigData.isEnableNotifyIconFixNotify)
intent.data?.schemeSpecificPart?.also { packageName ->
when (intent.action) { when (intent.action) {
Intent.ACTION_PACKAGE_ADDED -> { Intent.ACTION_PACKAGE_ADDED -> {
if (iconDatas.takeIf { e -> e.isNotEmpty() } if (iconDatas.takeIf { e -> e.isNotEmpty() }
@@ -706,7 +721,6 @@ object SystemUIHooker : YukiBaseHooker() {
/** 缓存图标数据 */ /** 缓存图标数据 */
private fun cachingIconDatas() { private fun cachingIconDatas() {
iconDatas.clear() iconDatas.clear()
grayscaleIconResults.clear()
IconPackParams(param = this).iconDatas.apply { if (isNotEmpty()) forEach { iconDatas.add(it) } } IconPackParams(param = this).iconDatas.apply { if (isNotEmpty()) forEach { iconDatas.add(it) } }
} }
@@ -721,7 +735,6 @@ object SystemUIHooker : YukiBaseHooker() {
/** 获取可读写状态 */ /** 获取可读写状态 */
return prefs.isPreferencesAvailable.also { return prefs.isPreferencesAvailable.also {
isUsingCachingMethod = true isUsingCachingMethod = true
prefs.clearCache()
cachingIconDatas() cachingIconDatas()
if (isRefreshCacheOnly) return@also if (isRefreshCacheOnly) return@also
refreshStatusBarIcons() refreshStatusBarIcons()
@@ -739,9 +752,9 @@ object SystemUIHooker : YukiBaseHooker() {
/** 强制回写系统的状态栏图标样式为原生 */ /** 强制回写系统的状态栏图标样式为原生 */
injectMember { injectMember {
method { method {
name = "shouldSubstituteSmallIcon" name { it == "shouldSubstituteSmallIcon" || it == "shouldSubstituteSmallIconForStatusBarNotification" }
param(ExpandedNotificationClass) param { it[0] extends StatusBarNotificationClass }
} }.all()
replaceToFalse() replaceToFalse()
} }
/** 强制回写系统的状态栏图标样式为原生 */ /** 强制回写系统的状态栏图标样式为原生 */
@@ -749,7 +762,7 @@ object SystemUIHooker : YukiBaseHooker() {
var isUseLegacy = false var isUseLegacy = false
method { method {
name = "getSmallIcon" name = "getSmallIcon"
param(ExpandedNotificationClass, IntType) param { it[0] extends StatusBarNotificationClass && it[1] == IntType }
}.remedys { }.remedys {
method { method {
name = "getSmallIcon" name = "getSmallIcon"
@@ -779,7 +792,7 @@ object SystemUIHooker : YukiBaseHooker() {
injectMember { injectMember {
method { method {
name = "onDarkChanged" name = "onDarkChanged"
param(VagueType, FloatType, IntType) paramCount { it > 0 }
} }
afterHook { afterHook {
field { name = "mNotificationIcons" }.get(instance).cast<ViewGroup>()?.also { field { name = "mNotificationIcons" }.get(instance).cast<ViewGroup>()?.also {
@@ -794,7 +807,7 @@ object SystemUIHooker : YukiBaseHooker() {
isDarkIconMode = false isDarkIconMode = false
updateStatusBarIconColor(it, isDarkIconMode = false) updateStatusBarIconColor(it, isDarkIconMode = false)
} }
else -> updateStatusBarIconColor(it, isDarkIconMode = false, args().last().int()) else -> updateStatusBarIconColor(it, isDarkIconMode = false, args(index = 2).int())
} }
} }
} }
@@ -891,35 +904,13 @@ object SystemUIHooker : YukiBaseHooker() {
} }
/** 注入原生通知包装纸实例 */ /** 注入原生通知包装纸实例 */
NotificationHeaderViewWrapperClass.hook { NotificationHeaderViewWrapperClass.hook {
/** 修复下拉通知图标自动设置回 APP 图标的方法 */
injectMember { injectMember {
method { name { it == "resolveHeaderViews" || it == "handleHeaderViews" || it == "resolveViews" } } method { name { it == "resolveHeaderViews" || it == "handleHeaderViews" || it == "resolveViews" } }
afterHook { afterHook { hookNotificationViewWrapper(instance) }
/** 忽略较旧版本 - 在没有 MIUI 通知栏样式的时候可能出现奇怪的问题 */
if (isNotHasAbsoluteMiuiStyle && isShowMiuiStyle) return@afterHook
/** 获取小图标 */
val iconImageView = NotificationHeaderViewWrapperClass.toClassOrNull()
?.field { name = "mIcon" }?.get(instance)?.cast<ImageView>() ?: return@afterHook
/** 获取 [ExpandableNotificationRowClass] */
val rowPair = instance.getRowPair()
/** 获取 [StatusBarNotification] */
val expandedNf = rowPair.second.getSbn()
/** 通知是否展开 */
var isExpanded = rowPair.first
/** 获取优先级 */
val importance =
(iconImageView.context.getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager?)
?.getNotificationChannel(expandedNf?.notification?.channelId)?.importance ?: 0
/** 非最小化优先级的通知全部设置为展开状态 */
if (importance != 1) isExpanded = true
/** 执行 Hook */
compatNotifyIcon(iconImageView.context, expandedNf, iconImageView, isExpanded)
} }
injectMember {
method { name = "onContentUpdated" }
afterHook { hookNotificationViewWrapper(instance) }
} }
} }
/** 修改 MIUI 风格通知栏的通知图标 */ /** 修改 MIUI 风格通知栏的通知图标 */

View File

@@ -29,7 +29,7 @@ import android.graphics.Color
import com.fankes.miui.notify.bean.IconDataBean import com.fankes.miui.notify.bean.IconDataBean
import com.fankes.miui.notify.data.ConfigData import com.fankes.miui.notify.data.ConfigData
import com.fankes.miui.notify.utils.factory.* import com.fankes.miui.notify.utils.factory.*
import com.highcapable.yukihookapi.hook.factory.modulePrefs import com.highcapable.yukihookapi.hook.factory.prefs
import com.highcapable.yukihookapi.hook.param.PackageParam import com.highcapable.yukihookapi.hook.param.PackageParam
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
@@ -47,7 +47,7 @@ class IconPackParams(private val context: Context? = null, private val param: Pa
* 已存储的 JSON 数据 * 已存储的 JSON 数据
* @return [String] * @return [String]
*/ */
internal val storageDataJson get() = (context?.modulePrefs ?: param?.prefs)?.direct()?.get(ConfigData.NOTIFY_ICONS_DATA) internal val storageDataJson get() = (context?.prefs() ?: param?.prefs)?.get(ConfigData.NOTIFY_ICONS_DATA)
/** /**
* 获取图标数据 * 获取图标数据
@@ -134,5 +134,5 @@ class IconPackParams(private val context: Context? = null, private val param: Pa
* 保存图标数据 * 保存图标数据
* @param dataJson 图标数据 JSON * @param dataJson 图标数据 JSON
*/ */
fun save(dataJson: String) = context?.modulePrefs?.put(ConfigData.NOTIFY_ICONS_DATA, dataJson) fun save(dataJson: String) = context?.prefs()?.edit { put(ConfigData.NOTIFY_ICONS_DATA, dataJson) }
} }

View File

@@ -25,7 +25,7 @@ package com.fankes.miui.notify.params.factory
import android.content.Context import android.content.Context
import com.fankes.miui.notify.bean.IconDataBean import com.fankes.miui.notify.bean.IconDataBean
import com.highcapable.yukihookapi.hook.factory.modulePrefs import com.highcapable.yukihookapi.hook.factory.prefs
import com.highcapable.yukihookapi.hook.param.PackageParam import com.highcapable.yukihookapi.hook.param.PackageParam
/** /**
@@ -38,14 +38,14 @@ fun PackageParam.isAppNotifyHookOf(bean: IconDataBean) = prefs.getBoolean(bean.t
* 获取此 APP 的通知图标是否被 Hook * 获取此 APP 的通知图标是否被 Hook
* @param bean 图标 bean * @param bean 图标 bean
*/ */
fun Context.isAppNotifyHookOf(bean: IconDataBean) = modulePrefs.getBoolean(bean.toEnabledName(), bean.isEnabled) fun Context.isAppNotifyHookOf(bean: IconDataBean) = prefs().getBoolean(bean.toEnabledName(), bean.isEnabled)
/** /**
* 设置 Hook 此 APP 的通知图标 * 设置 Hook 此 APP 的通知图标
* @param bean 图标 bean * @param bean 图标 bean
* @param isHook 是否 Hook * @param isHook 是否 Hook
*/ */
fun Context.putAppNotifyHookOf(bean: IconDataBean, isHook: Boolean) = modulePrefs.putBoolean(bean.toEnabledName(), isHook) fun Context.putAppNotifyHookOf(bean: IconDataBean, isHook: Boolean) = prefs().edit { putBoolean(bean.toEnabledName(), isHook) }
/** /**
* 获取此 APP 的通知图标是否被全部 Hook * 获取此 APP 的通知图标是否被全部 Hook
@@ -57,11 +57,11 @@ fun PackageParam.isAppNotifyHookAllOf(bean: IconDataBean) = prefs.getBoolean(bea
* 获取此 APP 的通知图标是否被全部 Hook * 获取此 APP 的通知图标是否被全部 Hook
* @param bean 图标 bean * @param bean 图标 bean
*/ */
fun Context.isAppNotifyHookAllOf(bean: IconDataBean) = modulePrefs.getBoolean(bean.toEnabledAllName(), bean.isEnabledAll) fun Context.isAppNotifyHookAllOf(bean: IconDataBean) = prefs().getBoolean(bean.toEnabledAllName(), bean.isEnabledAll)
/** /**
* 设置全部 Hook 此 APP 的通知图标 * 设置全部 Hook 此 APP 的通知图标
* @param bean 图标 bean * @param bean 图标 bean
* @param isHook 是否 Hook * @param isHook 是否 Hook
*/ */
fun Context.putAppNotifyHookAllOf(bean: IconDataBean, isHook: Boolean) = modulePrefs.putBoolean(bean.toEnabledAllName(), isHook) fun Context.putAppNotifyHookAllOf(bean: IconDataBean, isHook: Boolean) = prefs().edit { putBoolean(bean.toEnabledAllName(), isHook) }

View File

@@ -158,13 +158,12 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
binding.mainTextVersion.text = "模块版本:$moduleVersion $pendingFlag" binding.mainTextVersion.text = "模块版本:$moduleVersion $pendingFlag"
binding.mainTextMiuiVersion.text = "系统版本:[$androidVersionCodeName] $miuiFullVersion" binding.mainTextMiuiVersion.text = "系统版本:[$androidVersionCodeName] $miuiFullVersion"
binding.warnSCountDisTip.isGone = miuiVersionCode > 12.5 binding.warnSCountDisTip.isGone = miuiVersionCode > 12.5
binding.warnMiuiNotifyStyleTip.isGone = miuiVersionCode > 12 binding.warnMiuiNotifyStyleTip.isGone = miuiVersionCode > 11
binding.statusIconCountText.text = ConfigData.liftedStatusIconCount.toString() binding.statusIconCountText.text = ConfigData.liftedStatusIconCount.toString()
binding.notifyIconAutoSyncText.text = ConfigData.notifyIconFixAutoTime binding.notifyIconAutoSyncText.text = ConfigData.notifyIconFixAutoTime
binding.moduleEnableSwitch.bind(ConfigData.ENABLE_MODULE) { binding.moduleEnableSwitch.bind(ConfigData.ENABLE_MODULE) {
onInitialize { onInitialize {
binding.moduleEnableLogSwitch.isVisible = it binding.moduleEnableLogItem.isVisible = it
binding.expAllDebugLogButton.isVisible = it && ConfigData.isEnableModuleLog
binding.colorIconHookItem.isVisible = it binding.colorIconHookItem.isVisible = it
binding.statusIconCountItem.isVisible = isLowerAndroidR.not() && it binding.statusIconCountItem.isVisible = isLowerAndroidR.not() && it
binding.notifyStyleConfigItem.isVisible = it binding.notifyStyleConfigItem.isVisible = it
@@ -177,7 +176,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
} }
} }
binding.moduleEnableLogSwitch.bind(ConfigData.ENABLE_MODULE_LOG) { binding.moduleEnableLogSwitch.bind(ConfigData.ENABLE_MODULE_LOG) {
onInitialize { binding.expAllDebugLogButton.isVisible = it && ConfigData.isEnableModule } onInitialize { binding.expAllDebugLogButton.isVisible = it }
onChanged { onChanged {
reinitialize() reinitialize()
SystemUITool.refreshSystemUI(context = this@MainActivity, isRefreshCacheOnly = true) SystemUITool.refreshSystemUI(context = this@MainActivity, isRefreshCacheOnly = true)
@@ -209,9 +208,32 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
} else applyChangesAndRefresh() } else applyChangesAndRefresh()
} }
} }
binding.notifyIconForceSystemColorSwitch.bind(ConfigData.ENABLE_NOTIFY_ICON_FORCE_SYSTEM_COLOR) {
isAutoApplyChanges = false
onChanged {
/** 应用更改并刷新系统界面 */
fun applyChangesAndRefresh() {
applyChangesAndReinitialize()
SystemUITool.refreshSystemUI(context = this@MainActivity)
}
if (it) showDialog {
title = "破坏性功能警告"
msg = "开启这个功能后,任何通知栏中的通知图标都会忽略图标自身的着色属性,全部使用系统默认颜色 (系统提供的统一色调) 着色。\n\n" +
"此功能仅面向一些追求图标美观度的用户,我们不推荐开启这个功能,且发生任何 BUG 都不会去修复,仍然继续开启吗?"
confirmButton { applyChangesAndRefresh() }
cancelButton { cancelChanges() }
noCancelable()
} else applyChangesAndRefresh()
}
}
binding.notifyIconForceAppIconSwitch.bind(ConfigData.ENABLE_NOTIFY_ICON_FORCE_APP_ICON) { binding.notifyIconForceAppIconSwitch.bind(ConfigData.ENABLE_NOTIFY_ICON_FORCE_APP_ICON) {
isAutoApplyChanges = false isAutoApplyChanges = false
onInitialize { binding.notifyIconCustomCornerItem.isVisible = isLowerAndroidR.not() && it.not() } onInitialize {
arrayOf(
binding.notifyIconCustomCornerItem,
binding.notifyIconForceSystemColorItem
).forEach { e -> e.isVisible = isLowerAndroidR.not() && it.not() }
}
onChanged { onChanged {
/** 应用更改并刷新系统界面 */ /** 应用更改并刷新系统界面 */
fun applyChangesAndRefresh() { fun applyChangesAndRefresh() {

View File

@@ -356,12 +356,12 @@ val Context.systemAccentColor
/** /**
* 获取系统壁纸颜色 * 获取系统壁纸颜色
* @return [Int] 无法获取时返回透明 * @return [Int] 无法获取时返回默认颜
*/ */
val Context.wallpaperColor val Context.wallpaperColor
get() = safeOfNan { get() = runCatching {
WallpaperManager.getInstance(this).getWallpaperColors(WallpaperManager.FLAG_SYSTEM)?.primaryColor?.toArgb() ?: 0 WallpaperManager.getInstance(this).getWallpaperColors(WallpaperManager.FLAG_SYSTEM)?.primaryColor?.toArgb()
} }.getOrNull() ?: (if (isSystemInDarkMode) 0xFFD8D8D8.toInt() else 0xFF707173.toInt())
/** /**
* 获取较浅的颜色 * 获取较浅的颜色

View File

@@ -0,0 +1,84 @@
/*
* MIUINativeNotifyIcon - Fix the native notification bar icon function abandoned by the MIUI development team.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/MIUINativeNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
* and/or modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2023/4/17.
*/
package com.fankes.miui.notify.utils.tool
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.graphics.drawable.Icon
import android.os.Build
import androidx.core.graphics.drawable.toBitmap
import com.fankes.miui.notify.BuildConfig
import com.fankes.miui.notify.R
import com.fankes.miui.notify.utils.factory.appIconOf
/**
* 模块更新激活提醒通知工具类
*/
object ActivationPromptTool {
/** 当前模块的包名 */
private const val MODULE_PACKAGE_NAME = BuildConfig.APPLICATION_ID
/** 推送通知的渠道名称 */
private const val NOTIFY_CHANNEL = "activationPromptId"
/**
* 推送提醒通知
* @param context 当前实例
* @param packageName 当前 APP 包名
*/
fun prompt(context: Context, packageName: String) {
if (packageName != BuildConfig.APPLICATION_ID) return
context.getSystemService(NotificationManager::class.java)?.apply {
createNotificationChannel(
NotificationChannel(
NOTIFY_CHANNEL, "MIUI 原生通知图标 - 版本更新",
NotificationManager.IMPORTANCE_DEFAULT
).apply { enableLights(false) }
)
notify(packageName.hashCode(), Notification.Builder(context, NOTIFY_CHANNEL).apply {
setShowWhen(true)
setContentTitle("模块已更新")
setContentText("点按通知打开模块以完成新版本激活。")
setColor(0xFFE06818.toInt())
setAutoCancel(true)
setSmallIcon(Icon.createWithResource(MODULE_PACKAGE_NAME, R.drawable.ic_notify_update))
setLargeIcon(context.appIconOf(packageName)?.toBitmap())
setContentIntent(
PendingIntent.getActivity(
context, packageName.hashCode(),
Intent().apply {
component = ComponentName(MODULE_PACKAGE_NAME, "${MODULE_PACKAGE_NAME}.ui.activity.MainActivity")
flags = Intent.FLAG_ACTIVITY_NEW_TASK
}, if (Build.VERSION.SDK_INT < 31) PendingIntent.FLAG_UPDATE_CURRENT else PendingIntent.FLAG_IMMUTABLE
)
)
}.build())
}
}
}

View File

@@ -35,7 +35,7 @@ import java.io.Serializable
import java.util.* import java.util.*
/** /**
* 获取 Github Release 最新版本工具类 * 获取 GitHub Release 最新版本工具类
*/ */
object GithubReleaseTool { object GithubReleaseTool {
@@ -129,7 +129,7 @@ object GithubReleaseTool {
} }
/** /**
* Github Release bean * GitHub Release bean
* @param name 版本名称 * @param name 版本名称
* @param htmlUrl 网页地址 * @param htmlUrl 网页地址
* @param content 更新日志 * @param content 更新日志

View File

@@ -24,7 +24,7 @@ package com.fankes.miui.notify.utils.tool
import android.content.Context import android.content.Context
import com.fankes.miui.notify.utils.factory.showDialog import com.fankes.miui.notify.utils.factory.showDialog
import com.highcapable.yukihookapi.hook.factory.modulePrefs import com.highcapable.yukihookapi.hook.factory.prefs
import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData
import java.util.* import java.util.*
@@ -41,8 +41,8 @@ object I18nWarnTool {
* @param context 实例 * @param context 实例
*/ */
fun checkingOrShowing(context: Context) { fun checkingOrShowing(context: Context) {
fun saveReaded() = context.modulePrefs.put(LOCALE_WARN_READED, value = true) fun saveReaded() = context.prefs().edit { put(LOCALE_WARN_READED, value = true) }
if (Locale.getDefault().language.startsWith("zh").not() && context.modulePrefs.get(LOCALE_WARN_READED).not()) if (Locale.getDefault().language.startsWith("zh").not() && context.prefs().get(LOCALE_WARN_READED).not())
context.showDialog { context.showDialog {
title = "Notice of I18n Support" title = "Notice of I18n Support"
msg = "This Xposed Module is only for Chinese and the Chinese region.\n\n" + msg = "This Xposed Module is only for Chinese and the Chinese region.\n\n" +

View File

@@ -67,12 +67,15 @@ object IconRuleManagerTool {
/** 当前规则的通知图标颜色 */ /** 当前规则的通知图标颜色 */
private const val OS_COLOR = 0xFFE06818.toInt() private const val OS_COLOR = 0xFFE06818.toInt()
/** 同步地址 - Github Raw (代理) */ /** 同步地址 - GitHub Raw (直连) */
private const val SYNC_PROXY_URL = "https://raw.githubusercontentS.com/fankes/AndroidNotifyIconAdapt/main"
/** 同步地址 - Github Raw (直连) */
private const val SYNC_DIRECT_URL = "https://raw.githubusercontent.com/fankes/AndroidNotifyIconAdapt/main" private const val SYNC_DIRECT_URL = "https://raw.githubusercontent.com/fankes/AndroidNotifyIconAdapt/main"
/** 同步地址 - GitHub Raw (代理 - GitHub Proxy) */
private const val SYNC_PROXY_1_URL = "https://ghproxy.com/$SYNC_DIRECT_URL"
/** 同步地址 - GitHub Raw (代理 - 7ED Services) */
private const val SYNC_PROXY_2_URL = "https://raw.githubusercontentS.com/fankes/AndroidNotifyIconAdapt/main"
/** 云端规则展示地址 (OS) */ /** 云端规则展示地址 (OS) */
private const val RULES_TRAVELER_OS_URL = "https://fankes.github.io/AndroidNotifyIconAdapt/?notify-rules-miui" private const val RULES_TRAVELER_OS_URL = "https://fankes.github.io/AndroidNotifyIconAdapt/?notify-rules-miui"
@@ -104,13 +107,19 @@ object IconRuleManagerTool {
} }
binding.sourceFromTextLin.isVisible = sourceType == IconRuleSourceSyncType.CUSTOM_URL binding.sourceFromTextLin.isVisible = sourceType == IconRuleSourceSyncType.CUSTOM_URL
binding.sourceTravelerLin.isVisible = sourceType != IconRuleSourceSyncType.CUSTOM_URL binding.sourceTravelerLin.isVisible = sourceType != IconRuleSourceSyncType.CUSTOM_URL
binding.sourceRadio1.isChecked = sourceType == IconRuleSourceSyncType.GITHUB_RAW_PROXY binding.sourceRadio0.isChecked = sourceType == IconRuleSourceSyncType.GITHUB_RAW_PROXY_1
binding.sourceRadio1.isChecked = sourceType == IconRuleSourceSyncType.GITHUB_RAW_PROXY_2
binding.sourceRadio2.isChecked = sourceType == IconRuleSourceSyncType.GITHUB_RAW_DIRECT binding.sourceRadio2.isChecked = sourceType == IconRuleSourceSyncType.GITHUB_RAW_DIRECT
binding.sourceRadio3.isChecked = sourceType == IconRuleSourceSyncType.CUSTOM_URL binding.sourceRadio3.isChecked = sourceType == IconRuleSourceSyncType.CUSTOM_URL
binding.sourceRadio0.setOnClickListener {
binding.sourceFromTextLin.isVisible = false
binding.sourceTravelerLin.isVisible = true
sourceType = IconRuleSourceSyncType.GITHUB_RAW_PROXY_1
}
binding.sourceRadio1.setOnClickListener { binding.sourceRadio1.setOnClickListener {
binding.sourceFromTextLin.isVisible = false binding.sourceFromTextLin.isVisible = false
binding.sourceTravelerLin.isVisible = true binding.sourceTravelerLin.isVisible = true
sourceType = IconRuleSourceSyncType.GITHUB_RAW_PROXY sourceType = IconRuleSourceSyncType.GITHUB_RAW_PROXY_2
} }
binding.sourceRadio2.setOnClickListener { binding.sourceRadio2.setOnClickListener {
binding.sourceFromTextLin.isVisible = false binding.sourceFromTextLin.isVisible = false
@@ -189,7 +198,8 @@ object IconRuleManagerTool {
callback: () -> Unit callback: () -> Unit
) { ) {
when (sourceType) { when (sourceType) {
IconRuleSourceSyncType.GITHUB_RAW_PROXY -> onRefreshing(context, SYNC_PROXY_URL, callback) IconRuleSourceSyncType.GITHUB_RAW_PROXY_1 -> onRefreshing(context, SYNC_PROXY_1_URL, callback)
IconRuleSourceSyncType.GITHUB_RAW_PROXY_2 -> onRefreshing(context, SYNC_PROXY_2_URL, callback)
IconRuleSourceSyncType.GITHUB_RAW_DIRECT -> onRefreshing(context, SYNC_DIRECT_URL, callback) IconRuleSourceSyncType.GITHUB_RAW_DIRECT -> onRefreshing(context, SYNC_DIRECT_URL, callback)
IconRuleSourceSyncType.CUSTOM_URL -> IconRuleSourceSyncType.CUSTOM_URL ->
if (customUrl.isNotBlank()) if (customUrl.isNotBlank())

View File

@@ -27,7 +27,7 @@ import com.fankes.miui.notify.BuildConfig
import com.fankes.miui.notify.utils.factory.openBrowser import com.fankes.miui.notify.utils.factory.openBrowser
import com.fankes.miui.notify.utils.factory.showDialog import com.fankes.miui.notify.utils.factory.showDialog
import com.highcapable.yukihookapi.YukiHookAPI import com.highcapable.yukihookapi.YukiHookAPI
import com.highcapable.yukihookapi.hook.factory.modulePrefs import com.highcapable.yukihookapi.hook.factory.prefs
import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData
/** /**
@@ -43,8 +43,8 @@ object YukiPromoteTool {
* @param context 实例 * @param context 实例
*/ */
fun promote(context: Context) { fun promote(context: Context) {
fun saveReaded() = context.modulePrefs.put(YUKI_PROMOTE_READED, value = true) fun saveReaded() = context.prefs().edit { put(YUKI_PROMOTE_READED, value = true) }
if (context.modulePrefs.get(YUKI_PROMOTE_READED).not()) if (context.prefs().get(YUKI_PROMOTE_READED).not())
context.showDialog { context.showDialog {
title = "面向开发者的推广" title = "面向开发者的推广"
msg = "你想快速拥有一个自己的 Xposed 模块吗,你只需要拥有基础的 Android 开发经验以及使用 Kotlin 编程语言即可。\n\n" + msg = "你想快速拥有一个自己的 Xposed 模块吗,你只需要拥有基础的 Android 开发经验以及使用 Kotlin 编程语言即可。\n\n" +

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="#ffffff"
android:pathData="m522.8,93.9c-244.2,0 -442.1,173.2 -442.1,386.9 0,122.1 64.9,230.9 165.8,301.7v195.7l193.7,-117.5c26.8,4.4 54.3,7 82.6,7 244.2,0 442.1,-173.2 442.1,-386.9C965,267.1 767.1,93.9 522.8,93.9Z"
android:strokeWidth="1.10883" />
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="50dp"
android:height="50dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="#ffffff"
android:pathData="M906.4,791.6a247.9,247.9 0,0 0,-98.1 -186.5L808.3,399.4c0,-118.8 -85.1,-218.9 -197.4,-242.5v-4.7c0,-54.2 -44.5,-98.6 -98.8,-98.6 -54.3,0 -98.8,44.4 -98.8,98.6v4.7C300.8,180.5 215.7,280.4 215.7,399.4v205.8a247.7,247.7 0,0 0,-98.1 186.5h98.1v0.6h592.5v-0.6h98.1v-0.1zM491.1,970.4h24.5c64.3,0 117.8,-48.5 125.6,-110.7L383,859.8a126.8,126.8 0,0 0,125.6 110.7h-17.5z" />
</vector>

View File

@@ -253,17 +253,37 @@
android:layout_marginLeft="15dp" android:layout_marginLeft="15dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:layout_marginRight="15dp" android:layout_marginRight="15dp"
android:layout_marginBottom="5dp"
android:text="启用模块" android:text="启用模块"
android:textColor="@color/colorTextGray" android:textColor="@color/colorTextGray"
android:textSize="15sp" /> android:textSize="15sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginBottom="10dp"
android:alpha="0.6"
android:lineSpacingExtra="6dp"
android:text="模块关闭后一切功能都将彻底停止工作。"
android:textColor="@color/colorTextDark"
android:textSize="12sp" />
<LinearLayout
android:id="@+id/module_enable_log_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:orientation="vertical">
<com.fankes.miui.notify.ui.widget.MaterialSwitch <com.fankes.miui.notify.ui.widget.MaterialSwitch
android:id="@+id/module_enable_log_switch" android:id="@+id/module_enable_log_switch"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="35dp" android:layout_height="30dp"
android:layout_marginLeft="15dp" android:layout_marginLeft="15dp"
android:layout_marginRight="15dp" android:layout_marginRight="15dp"
android:layout_marginBottom="5dp" android:layout_marginBottom="10dp"
android:text="启用调试日志" android:text="启用调试日志"
android:textColor="@color/colorTextGray" android:textColor="@color/colorTextGray"
android:textSize="15sp" /> android:textSize="15sp" />
@@ -288,13 +308,13 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="15dp" android:layout_marginLeft="15dp"
android:layout_marginRight="15dp" android:layout_marginRight="15dp"
android:layout_marginBottom="10dp"
android:alpha="0.6" android:alpha="0.6"
android:lineSpacingExtra="6dp" android:lineSpacingExtra="6dp"
android:text="模块关闭后一切功能都将彻底停止工作。" android:text="默认情况下不建议开启此选项,仅在模块故障时开启,此时你可以发送调试日志给开发者帮助我们快速定位问题。"
android:textColor="@color/colorTextDark" android:textColor="@color/colorTextDark"
android:textSize="12sp" /> android:textSize="12sp" />
</LinearLayout> </LinearLayout>
</LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/status_icon_count_item" android:id="@+id/status_icon_count_item"
@@ -767,7 +787,7 @@
android:layout_marginRight="15dp" android:layout_marginRight="15dp"
android:alpha="0.6" android:alpha="0.6"
android:lineSpacingExtra="6dp" android:lineSpacingExtra="6dp"
android:text="⚠️ 在 MIUI 11、12 上可能需要 Root 权限才能打开。" android:text="⚠️ 在 MIUI 11 上可能需要 Root 权限才能打开。"
android:textColor="@color/colorTextDark" android:textColor="@color/colorTextDark"
android:textSize="12sp" android:textSize="12sp"
android:textStyle="bold" /> android:textStyle="bold" />
@@ -862,6 +882,34 @@
android:textStyle="bold" /> android:textStyle="bold" />
</LinearLayout> </LinearLayout>
<LinearLayout
android:id="@+id/notify_icon_force_system_color_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.fankes.miui.notify.ui.widget.MaterialSwitch
android:id="@+id/notify_icon_force_system_color_switch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:text="通知栏中的图标使用系统默认着色"
android:textColor="@color/colorTextGray"
android:textSize="15sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0.6"
android:lineSpacingExtra="6dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:text="此选项默认关闭,开启后下拉通知栏中的通知图标将忽略图标自身的着色属性,全部使用系统默认颜色 (系统提供的统一色调) 着色,这是一个破坏原生通知图标的行为,仅针对部分有需要的用户而添加,我们不推荐开启这个功能,请根据个人偏好进行选择是否需要开启。"
android:textColor="@color/colorTextDark"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@@ -24,18 +24,25 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/source_radio_0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="GitHub Raw (GitHub Proxy)"
app:buttonTint="@color/colorPrimaryAccent" />
<com.google.android.material.radiobutton.MaterialRadioButton <com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/source_radio_1" android:id="@+id/source_radio_1"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Github Raw (7ED Services)" android:text="GitHub Raw (7ED Services)"
app:buttonTint="@color/colorPrimaryAccent" /> app:buttonTint="@color/colorPrimaryAccent" />
<com.google.android.material.radiobutton.MaterialRadioButton <com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/source_radio_2" android:id="@+id/source_radio_2"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Github Raw (直连)" android:text="GitHub Raw (直连)"
app:buttonTint="@color/colorPrimaryAccent" /> app:buttonTint="@color/colorPrimaryAccent" />
<com.google.android.material.radiobutton.MaterialRadioButton <com.google.android.material.radiobutton.MaterialRadioButton

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/> <background android:drawable="@color/ic_launcher_background" />
<foreground android:drawable="@mipmap/ic_launcher_foreground"/> <foreground android:drawable="@mipmap/ic_launcher_foreground" />
<monochrome android:drawable="@mipmap/ic_launcher_foreground" />
</adaptive-icon> </adaptive-icon>

View File

@@ -1,13 +1,24 @@
plugins { plugins {
id 'com.android.application' version '7.4.1' apply false id 'com.android.application' version '7.4.1' apply false
id 'com.android.library' version '7.4.1' apply false id 'com.android.library' version '7.4.1' apply false
id 'org.jetbrains.kotlin.android' version '1.7.22' apply false id 'org.jetbrains.kotlin.android' version '1.8.20' apply false
id 'com.google.devtools.ksp' version '1.8.20-1.0.10' apply false
} }
ext { ext {
appVersionName = "2.9" android = [
appVersionCode = 35 compileSdk: 33,
enableR8 = true minSdk : 28,
targetSdk : 33
]
app = [
versionName : '2.101',
versionCode : 41,
signingConfigs: [
secretConfigsDirPath : "${projectDir.getAbsolutePath()}/.secret",
secretConfigsFileName: "key_store_secret.json"
]
]
} }
task clean(type: Delete) { task clean(type: Delete) {

View File

@@ -1,6 +1,6 @@
#Wed May 25 04:36:53 CST 2022 #Wed May 25 04:36:53 CST 2022
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME