14 Commits
2.95 ... 2.99

21 changed files with 333 additions and 103 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.95-green)](https://github.com/fankes/MIUINativeNotifyIcon/releases) [![Blank](https://img.shields.io/badge/version-v2.99-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)

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.10'
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.1.8' ksp 'com.highcapable.yukihookapi:ksp-xposed:1.1.10'
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,8 +36,11 @@ 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 (代理 - 7ED Services) */
const val GITHUB_RAW_PROXY_2 = 1000
/** GitHub Raw (直连) */ /** 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

@@ -45,6 +45,7 @@ object HookEntry : IYukiHookXposedInit {
elements(PRIORITY) elements(PRIORITY)
} }
isDebug = false isDebug = false
isEnablePrefsBridgeCache = false
} }
override fun onHook() = encase { override fun onHook() = encase {

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
@@ -438,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
@@ -466,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)
@@ -692,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() }

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)?.direct()?.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

@@ -163,8 +163,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
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

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

@@ -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 (代理) */
private const val SYNC_PROXY_URL = "https://raw.githubusercontentS.com/fankes/AndroidNotifyIconAdapt/main"
/** 同步地址 - GitHub Raw (直连) */ /** 同步地址 - 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,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"
@@ -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,6 +24,13 @@
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"

View File

@@ -2,4 +2,5 @@
<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.95" android = [
appVersionCode = 36 compileSdk: 33,
enableR8 = true minSdk : 28,
targetSdk : 33
]
app = [
versionName : '2.99',
versionCode : 39,
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