23 Commits
1.76 ... 1.85

Author SHA1 Message Date
c02bc2314a Update version to 1.85 2022-05-31 04:06:23 +08:00
d177620784 Added notify icon custom corner function 2022-05-31 03:43:46 +08:00
354d0e1961 Update misc 2022-05-31 03:43:42 +08:00
bc1f379650 Update YukiHookAPI 2022-05-31 02:13:53 +08:00
63512254da Update version to 1.8 2022-05-30 03:58:50 +08:00
69c5003af1 Changed contributing way 2022-05-30 03:46:30 +08:00
ac17f3ae55 Added notify icon in notify panel used app icon function 2022-05-30 03:24:40 +08:00
d469adc667 Added warn dialog when enable replace all notify icon 2022-05-30 02:34:39 +08:00
2bb2218145 Merge code 2022-05-30 02:09:45 +08:00
aae8a27fcc Merge to new way support receiver callback 2022-05-30 01:58:28 +08:00
3b31e2c255 Merge systemBar support with native 2022-05-30 00:52:03 +08:00
f111e7d53c Added YukiPromoteTool 2022-05-30 00:38:08 +08:00
327f2139b8 Update YukiHookAPI 2022-05-29 04:08:16 +08:00
adb1f174ad Update YukiHookAPI 2022-05-27 03:36:28 +08:00
373d5c6cb8 Merge code 2022-05-25 04:38:40 +08:00
aba5e3c23c Update YukiHookAPI 2022-05-25 04:27:01 +08:00
8a2f0aca83 Changed FunctionFactory.kt 2022-05-12 01:10:22 +08:00
a0a4d08612 Changed Xposed Scope 2022-05-11 21:52:55 +08:00
25747b2041 Update YukiHookAPI 2022-05-10 01:53:17 +08:00
8de1abf679 Update version to 1.77 2022-05-09 16:08:08 +08:00
b97de07843 Update misc 2022-05-09 16:01:41 +08:00
b497189549 修复媒体通知面板不能被透明的问题,新增媒体通知自动展开功能 2022-05-09 16:01:35 +08:00
1ca659dd6a Merge code 2022-05-09 15:00:08 +08:00
21 changed files with 642 additions and 430 deletions

2
.idea/misc.xml generated
View File

@@ -11,7 +11,7 @@
<entry key="app/src/main/res/drawable/ic_notify_icon.xml" value="0.232" /> <entry key="app/src/main/res/drawable/ic_notify_icon.xml" value="0.232" />
<entry key="app/src/main/res/drawable/ic_system_clock.xml" value="0.232" /> <entry key="app/src/main/res/drawable/ic_system_clock.xml" value="0.232" />
<entry key="app/src/main/res/layout/activity_config.xml" value="0.4375" /> <entry key="app/src/main/res/layout/activity_config.xml" value="0.4375" />
<entry key="app/src/main/res/layout/activity_main.xml" value="0.31170825335892516" /> <entry key="app/src/main/res/layout/activity_main.xml" value="0.29182608695652174" />
<entry key="app/src/main/res/layout/adapter_config.xml" value="0.4375" /> <entry key="app/src/main/res/layout/adapter_config.xml" value="0.4375" />
<entry key="app/src/main/res/layout/dia_icon_filter.xml" value="0.4375" /> <entry key="app/src/main/res/layout/dia_icon_filter.xml" value="0.4375" />
<entry key="app/src/main/res/layout/dia_source_from.xml" value="0.4375" /> <entry key="app/src/main/res/layout/dia_source_from.xml" value="0.4375" />

View File

@@ -2,7 +2,7 @@
[![Blank](https://img.shields.io/badge/build-passing-brightgreen)](https://github.com/fankes/ColorOSNotifyIcon) [![Blank](https://img.shields.io/badge/build-passing-brightgreen)](https://github.com/fankes/ColorOSNotifyIcon)
[![Blank](https://img.shields.io/badge/license-AGPL3.0-blue)](https://github.com/fankes/ColorOSNotifyIcon/blob/master/LICENSE) [![Blank](https://img.shields.io/badge/license-AGPL3.0-blue)](https://github.com/fankes/ColorOSNotifyIcon/blob/master/LICENSE)
[![Blank](https://img.shields.io/badge/version-v1.76-green)](https://github.com/fankes/ColorOSNotifyIcon/releases) [![Blank](https://img.shields.io/badge/version-v1.85-green)](https://github.com/fankes/ColorOSNotifyIcon/releases)
[![Blank](https://img.shields.io/github/downloads/fankes/ColorOSNotifyIcon/total?label=Release)](https://github.com/fankes/ColorOSNotifyIcon/releases) [![Blank](https://img.shields.io/github/downloads/fankes/ColorOSNotifyIcon/total?label=Release)](https://github.com/fankes/ColorOSNotifyIcon/releases)
[![Blank](https://img.shields.io/github/downloads/Xposed-Modules-Repo/com.fankes.coloros.notify/total?label=LSPosed%20Repo&logo=Android&style=flat&labelColor=F48FB1&logoColor=ffffff)](https://github.com/Xposed-Modules-Repo/com.fankes.coloros.notify/releases) [![Blank](https://img.shields.io/github/downloads/Xposed-Modules-Repo/com.fankes.coloros.notify/total?label=LSPosed%20Repo&logo=Android&style=flat&labelColor=F48FB1&logoColor=ffffff)](https://github.com/Xposed-Modules-Repo/com.fankes.coloros.notify/releases)
[![Telegram](https://img.shields.io/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

@@ -31,6 +31,8 @@ android {
buildTypes { buildTypes {
release { release {
minifyEnabled rootProject.ext.enableR8 minifyEnabled rootProject.ext.enableR8
shrinkResources rootProject.ext.enableR8
zipAlignEnabled rootProject.ext.enableR8
signingConfig signingConfigs.debug signingConfig signingConfigs.debug
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
@@ -50,36 +52,22 @@ android {
buildFeatures { buildFeatures {
viewBinding true viewBinding true
} }
} lintOptions {
checkReleaseBuilds false
/** 移除无效耗时 lint Task */ }
tasks.whenTaskAdded {
task -> if (task.name == "lintVitalRelease") task.enabled = false
}
/** 移除无效耗时 lint Task */
tasks.whenTaskAdded {
task -> if (task.name == "lintVitalAnalyzeRelease") task.enabled = false
}
/** 移除无效耗时 lint Task */
tasks.whenTaskAdded {
task -> if (task.name == "lintVitalReportRelease") task.enabled = false
} }
dependencies { dependencies {
compileOnly 'de.robv.android.xposed:api:82' compileOnly 'de.robv.android.xposed:api:82'
implementation 'com.highcapable.yukihookapi:api:1.0.86' implementation 'com.highcapable.yukihookapi:api:1.0.92'
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.86' ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.92'
implementation "com.github.topjohnwu.libsu:core:3.1.2" implementation "com.github.topjohnwu.libsu:core:3.1.2"
implementation 'androidx.annotation:annotation:1.3.0' implementation 'androidx.annotation:annotation:1.3.0'
implementation 'com.geyifeng.immersionbar:immersionbar:3.2.0'
implementation 'com.geyifeng.immersionbar:immersionbar-ktx:3.2.0'
implementation 'com.squareup.okhttp3:okhttp:4.9.3' implementation 'com.squareup.okhttp3:okhttp:4.9.3'
implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1' implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.6.0' implementation 'com.google.android.material:material:1.6.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3' implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

View File

@@ -1,60 +0,0 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* 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 2022/3/24.
*/
@file:Suppress("MemberVisibilityCanBePrivate")
package com.fankes.coloros.notify.const
import com.fankes.coloros.notify.BuildConfig
/**
* 存储一些静态编译后的值
*/
object Const {
/** 当前模块的包名 */
const val MODULE_PACKAGE_NAME = BuildConfig.APPLICATION_ID
/** 当前模块的版本名称 */
const val MODULE_VERSION_NAME = BuildConfig.VERSION_NAME
/** 当前模块的版本号 */
const val MODULE_VERSION_CODE = BuildConfig.VERSION_CODE
/** 当前模块的版本校验 */
const val MODULE_VERSION_VERIFY = "${MODULE_VERSION_NAME}_${MODULE_VERSION_CODE}_202205090117"
/** 当前模块的版本校验标签 */
const val MODULE_VERSION_VERIFY_TAG = "module_version_verify"
/** 发送通讯广播号标签 - 模块激活状态 */
const val ACTION_MODULE_CHECKING_RECEIVER = "cnn_module_checking_action"
/** 接收通讯广播号标签 - 模块激活状态 */
const val ACTION_MODULE_HANDLER_RECEIVER = "cnn_module_handler_action"
/** 发送通讯广播号标签 - 通知系统界面刷新 */
const val ACTION_REMIND_CHECKING_RECEIVER = "cnn_remind_checking_action"
/** 接收通讯广播号标签 - 通知系统界面刷新 */
const val ACTION_REMIND_HANDLER_RECEIVER = "cnn_remind_handler_action"
}

View File

@@ -33,13 +33,16 @@ object DataConst {
val ENABLE_HIDE_ICON = PrefsData("_hide_icon", false) val ENABLE_HIDE_ICON = PrefsData("_hide_icon", false)
val ENABLE_ANDROID12_STYLE = PrefsData("_notify_android12_style", isUpperOfAndroidS) val ENABLE_ANDROID12_STYLE = PrefsData("_notify_android12_style", isUpperOfAndroidS)
val ENABLE_NOTIFY_ICON_FIX = PrefsData("_notify_icon_fix", true) val ENABLE_NOTIFY_ICON_FIX = PrefsData("_notify_icon_fix", true)
val ENABLE_NOTIFY_ICON_FORCE_APP_ICON = PrefsData("_notify_icon_force_app_icon", false)
val ENABLE_NOTIFY_ICON_FIX_NOTIFY = PrefsData("_notify_icon_fix_notify", true) val ENABLE_NOTIFY_ICON_FIX_NOTIFY = PrefsData("_notify_icon_fix_notify", true)
val REMOVE_DEV_NOTIFY = PrefsData("_remove_dev_notify", true) val REMOVE_DEV_NOTIFY = PrefsData("_remove_dev_notify", true)
val REMOVE_CHANGECP_NOTIFY = PrefsData("_remove_charge_complete_notify", false) val REMOVE_CHANGECP_NOTIFY = PrefsData("_remove_charge_complete_notify", false)
val REMOVE_DNDALERT_NOTIFY = PrefsData("_remove_dndalert_notify", false) val REMOVE_DNDALERT_NOTIFY = PrefsData("_remove_dndalert_notify", false)
val ENABLE_NOTIFY_ICON_FIX_AUTO = PrefsData("_enable_notify_icon_fix_auto", true) val ENABLE_NOTIFY_ICON_FIX_AUTO = PrefsData("_enable_notify_icon_fix_auto", true)
val ENABLE_NOTIFY_PANEL_ALPHA = PrefsData("_enable_notify_panel_alpha", false) val ENABLE_NOTIFY_PANEL_ALPHA = PrefsData("_enable_notify_panel_alpha", false)
val NOTIFY_PANEL_ALPHA = PrefsData("_notify_panel_alpha", 185) val ENABLE_NOTIFY_MEDIA_PANEL_AUTO_EXP = PrefsData("_enable_notify_media_panel_auto_exp", false)
val NOTIFY_ICON_CORNER = PrefsData("_notify_icon_corner", 10)
val NOTIFY_PANEL_ALPHA = PrefsData("_notify_panel_alpha_pst", 75)
val NOTIFY_ICON_DATAS = PrefsData("_notify_icon_datas", "") val NOTIFY_ICON_DATAS = PrefsData("_notify_icon_datas", "")
val NOTIFY_ICON_FIX_AUTO_TIME = PrefsData("_notify_icon_fix_auto_time", "07:00") val NOTIFY_ICON_FIX_AUTO_TIME = PrefsData("_notify_icon_fix_auto_time", "07:00")

View File

@@ -32,7 +32,7 @@ import com.highcapable.yukihookapi.hook.factory.encase
import com.highcapable.yukihookapi.hook.log.loggerW import com.highcapable.yukihookapi.hook.log.loggerW
import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit
@InjectYukiHookWithXposed @InjectYukiHookWithXposed(isUsingResourcesHook = false)
class HookEntry : IYukiHookXposedInit { class HookEntry : IYukiHookXposedInit {
override fun onInit() = configs { override fun onInit() = configs {
@@ -41,13 +41,15 @@ class HookEntry : IYukiHookXposedInit {
} }
override fun onHook() = encase { override fun onHook() = encase {
loadApp(SYSTEMUI_PACKAGE_NAME) {
when { when {
/** 不是 ColorOS 系统停止 Hook */ /** 不是 ColorOS 系统停止 Hook */
isNotColorOS -> loggerW(msg = "Aborted Hook -> This System is not ColorOS") isNotColorOS -> loggerW(msg = "Aborted Hook -> This System is not ColorOS")
/** Hook 被手动关闭停止 Hook */ /** Hook 被手动关闭停止 Hook */
prefs.get(DataConst.ENABLE_MODULE).not() -> loggerW(msg = "Aborted Hook -> Hook Closed") prefs.get(DataConst.ENABLE_MODULE).not() -> loggerW(msg = "Aborted Hook -> Hook Closed")
/** 开始 Hook */ /** 开始 Hook */
else -> loadApp(SYSTEMUI_PACKAGE_NAME, SystemUIHooker) else -> loadHooker(SystemUIHooker)
}
} }
} }
} }

View File

@@ -25,10 +25,9 @@
package com.fankes.coloros.notify.hook.entity package com.fankes.coloros.notify.hook.entity
import android.app.WallpaperManager import android.app.WallpaperManager
import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.res.ColorStateList
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.Color import android.graphics.Color
import android.graphics.Outline import android.graphics.Outline
@@ -36,6 +35,7 @@ import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.graphics.drawable.Icon import android.graphics.drawable.Icon
import android.graphics.drawable.VectorDrawable import android.graphics.drawable.VectorDrawable
import android.os.SystemClock
import android.service.notification.StatusBarNotification import android.service.notification.StatusBarNotification
import android.util.ArrayMap import android.util.ArrayMap
import android.view.View import android.view.View
@@ -45,7 +45,6 @@ import android.widget.ImageView
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import androidx.core.view.children import androidx.core.view.children
import com.fankes.coloros.notify.bean.IconDataBean import com.fankes.coloros.notify.bean.IconDataBean
import com.fankes.coloros.notify.const.Const
import com.fankes.coloros.notify.data.DataConst import com.fankes.coloros.notify.data.DataConst
import com.fankes.coloros.notify.hook.HookConst.ANDROID_PACKAGE_NAME import com.fankes.coloros.notify.hook.HookConst.ANDROID_PACKAGE_NAME
import com.fankes.coloros.notify.hook.HookConst.SYSTEMUI_PACKAGE_NAME import com.fankes.coloros.notify.hook.HookConst.SYSTEMUI_PACKAGE_NAME
@@ -55,6 +54,7 @@ import com.fankes.coloros.notify.param.IconPackParams
import com.fankes.coloros.notify.utils.drawable.drawabletoolbox.DrawableBuilder import com.fankes.coloros.notify.utils.drawable.drawabletoolbox.DrawableBuilder
import com.fankes.coloros.notify.utils.factory.* import com.fankes.coloros.notify.utils.factory.*
import com.fankes.coloros.notify.utils.tool.IconAdaptationTool import com.fankes.coloros.notify.utils.tool.IconAdaptationTool
import com.fankes.coloros.notify.utils.tool.SystemUITool
import com.highcapable.yukihookapi.hook.bean.VariousClass import com.highcapable.yukihookapi.hook.bean.VariousClass
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
import com.highcapable.yukihookapi.hook.factory.current import com.highcapable.yukihookapi.hook.factory.current
@@ -96,19 +96,34 @@ object SystemUIHooker : YukiBaseHooker() {
/** 原生存在的类 */ /** 原生存在的类 */
private const val IconManagerClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.icon.IconManager" private const val IconManagerClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.icon.IconManager"
/** ColorOS 存在的类 - 旧版本不存在 */
private const val OplusContrastColorUtilClass = "com.oplusos.util.OplusContrastColorUtil"
/** 原生存在的类 */ /** 原生存在的类 */
private const val PluginManagerImplClass = "$SYSTEMUI_PACKAGE_NAME.shared.plugins.PluginManagerImpl" private const val PluginManagerImplClass = "$SYSTEMUI_PACKAGE_NAME.shared.plugins.PluginManagerImpl"
/** 原生存在的类 */ /** 原生存在的类 */
private const val NotificationBackgroundViewClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.row.NotificationBackgroundView" private const val NotificationBackgroundViewClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.row.NotificationBackgroundView"
/** 原生存在的类 */
private const val PlayerViewHolderClass = "$SYSTEMUI_PACKAGE_NAME.media.PlayerViewHolder"
/** 原生存在的类 */
private const val MediaDataClass = "$SYSTEMUI_PACKAGE_NAME.media.MediaData"
/** ColorOS 存在的类 - 旧版本不存在 */
private const val OplusContrastColorUtilClass = "com.oplusos.util.OplusContrastColorUtil"
/** ColorOS 存在的类 - 旧版本不存在 */ /** ColorOS 存在的类 - 旧版本不存在 */
private const val OplusNotificationBackgroundViewClass = private const val OplusNotificationBackgroundViewClass =
"com.oplusos.systemui.statusbar.notification.row.OplusNotificationBackgroundView" "com.oplusos.systemui.statusbar.notification.row.OplusNotificationBackgroundView"
/** ColorOS 存在的类 - 旧版本不存在 */
private const val OplusMediaControlPanelClass = "com.oplusos.systemui.media.OplusMediaControlPanel"
/** ColorOS 存在的类 - 旧版本不存在 */
private const val OplusMediaViewControllerClass = "com.oplusos.systemui.media.OplusMediaViewController"
/** ColorOS 存在的类 - 旧版本不存在 */
private const val BasePlayViewHolderClass = "com.oplusos.systemui.media.base.BasePlayViewHolder"
/** 根据多个版本存在不同的包名相同的类 */ /** 根据多个版本存在不同的包名相同的类 */
private val OplusNotificationIconAreaControllerClass = VariousClass( private val OplusNotificationIconAreaControllerClass = VariousClass(
"com.oplusos.systemui.statusbar.phone.OplusNotificationIconAreaController", "com.oplusos.systemui.statusbar.phone.OplusNotificationIconAreaController",
@@ -188,6 +203,9 @@ object SystemUIHooker : YukiBaseHooker() {
/** 状态栏通知图标数组 */ /** 状态栏通知图标数组 */
private var notificationIconInstances = ArrayList<View>() private var notificationIconInstances = ArrayList<View>()
/** 媒体通知 [View] */
private var notificationPlayerView: View? = null
/** 通知栏通知控制器 */ /** 通知栏通知控制器 */
private var notificationPresenter: Any? = null private var notificationPresenter: Any? = null
@@ -197,65 +215,6 @@ object SystemUIHooker : YukiBaseHooker() {
/** 是否已经使用过缓存刷新功能 */ /** 是否已经使用过缓存刷新功能 */
private var isUsingCachingMethod = false private var isUsingCachingMethod = false
/** 是否已经注册广播 */
private var isRegisterReceiver = false
/** 用户解锁屏幕广播接收器 */
private val userPresentReceiver by lazy {
object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
/** 解锁后重新刷新状态栏图标防止系统重新设置它 */
if (isUsingCachingMethod) refreshStatusBarIcons()
}
}
}
/** 模块广播接收器 */
private val moduleCheckingReceiver by lazy {
object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
context?.sendBroadcast(Intent().apply {
action = Const.ACTION_MODULE_HANDLER_RECEIVER
putExtra("isRegular", true)
putExtra("isValied", intent?.isValiedModule)
})
}
}
}
/** 通知广播接收器 */
private val remindCheckingReceiver by lazy {
object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) = delayedRun(ms = 300) {
if (intent?.isValiedModule == true)
recachingPrefs(intent.getBooleanExtra("isRefreshCacheOnly", false))
context?.sendBroadcast(Intent().apply {
action = Const.ACTION_REMIND_HANDLER_RECEIVER
putExtra("isGrasp", true)
putExtra("isValied", intent?.isValiedModule)
})
}
}
}
/**
* 判断模块和宿主版本是否一致
* @return [Boolean]
*/
private val Intent.isValiedModule get() = getStringExtra(Const.MODULE_VERSION_VERIFY_TAG) == Const.MODULE_VERSION_VERIFY
/**
* 注册广播接收器
* @param context 实例
*/
private fun registerReceiver(context: Context) {
if (isRegisterReceiver) return
context.registerReceiver(userPresentReceiver, IntentFilter().apply { addAction(Intent.ACTION_USER_PRESENT) })
context.registerReceiver(moduleCheckingReceiver, IntentFilter().apply { addAction(Const.ACTION_MODULE_CHECKING_RECEIVER) })
context.registerReceiver(remindCheckingReceiver, IntentFilter().apply { addAction(Const.ACTION_REMIND_CHECKING_RECEIVER) })
isRegisterReceiver = true
}
/** /**
* 是否启用通知图标优化功能 * 是否启用通知图标优化功能
* @param isHooking 是否判断启用通知功能 - 默认:是 * @param isHooking 是否判断启用通知功能 - 默认:是
@@ -365,6 +324,7 @@ object SystemUIHooker : YukiBaseHooker() {
emptyParam() emptyParam()
}.call() }.call()
} }
modifyNotifyPanelAlpha(notificationPlayerView, isTint = true)
} }
/** /**
@@ -468,6 +428,13 @@ object SystemUIHooker : YukiBaseHooker() {
) = runInSafe { ) = runInSafe {
compatCustomIcon(isGrayscaleIcon, packageName).also { customPair -> compatCustomIcon(isGrayscaleIcon, packageName).also { customPair ->
when { when {
prefs.get(DataConst.ENABLE_NOTIFY_ICON_FORCE_APP_ICON) && isEnableHookColorNotifyIcon(isHooking = false) ->
iconView.apply {
/** 重新设置图标 */
setImageDrawable(appIcons[packageName] ?: context.findAppIcon(packageName))
/** 设置默认样式 */
setDefaultNotifyIconViewStyle()
}
customPair.first != null || isGrayscaleIcon -> iconView.apply { customPair.first != null || isGrayscaleIcon -> iconView.apply {
/** 设置不要裁切到边界 */ /** 设置不要裁切到边界 */
clipToOutline = false clipToOutline = false
@@ -495,7 +462,12 @@ object SystemUIHooker : YukiBaseHooker() {
/** 判断风格并开始 Hook */ /** 判断风格并开始 Hook */
if (isA12Style) { if (isA12Style) {
background = DrawableBuilder().rounded().solidColor(newApplyColor).build() /** 通知图标边框圆角大小 */
background = DrawableBuilder()
.rectangle()
.cornerRadius(prefs.get(DataConst.NOTIFY_ICON_CORNER).dp(context))
.solidColor(newApplyColor)
.build()
setColorFilter(newStyle) setColorFilter(newStyle)
setPadding(2.dp(context), 2.dp(context), 2.dp(context), 2.dp(context)) setPadding(2.dp(context), 2.dp(context), 2.dp(context), 2.dp(context))
} else { } else {
@@ -507,6 +479,46 @@ object SystemUIHooker : YukiBaseHooker() {
else -> iconView.apply { else -> iconView.apply {
/** 重新设置图标 */ /** 重新设置图标 */
setImageDrawable(nf.compatPushingIcon(drawable)) setImageDrawable(nf.compatPushingIcon(drawable))
/** 设置默认样式 */
setDefaultNotifyIconViewStyle()
}
}
/** 打印日志 */
printLogcat(tag = "NotifyIcon", iconView.context, packageName, isCustom = customPair.first != null, isGrayscaleIcon)
}
}
/**
* 设置通知面板背景透明度
* @param view 背景 View 实例
* @param drawable 背景实例
* @param isTint 是否着色 [view]
*/
private fun modifyNotifyPanelAlpha(view: View?, drawable: Drawable? = null, isTint: Boolean = false) {
prefs.get(DataConst.ENABLE_NOTIFY_PANEL_ALPHA).also { isEnabled ->
val currentAlpha = prefs.get(DataConst.NOTIFY_PANEL_ALPHA)
val currendColor = if (view?.context?.isSystemInDarkMode == true) 0xFF404040.toInt() else 0xFFFAFAFA.toInt()
/** 设置通知面板背景透明度 */
when {
isEnabled.not() -> {
if (isTint) view?.backgroundTintList = ColorStateList.valueOf(currendColor)
else drawable?.setTint(currendColor)
}
isTint.not() && view?.parent?.parent?.javaClass?.name?.contains(other = "ChildrenContainer") == true -> drawable?.alpha = 0
else -> {
currendColor.colorAlphaOf(currentAlpha / 100f).also {
if (isTint) view?.backgroundTintList = ColorStateList.valueOf(it)
else drawable?.setTint(it)
}
}
}
/** 移除阴影效果 */
if (isEnabled) view?.elevation = 0f
}
}
/** 设置默认通知栏通知图标样式 */
private fun ImageView.setDefaultNotifyIconViewStyle() {
/** 设置裁切到边界 */ /** 设置裁切到边界 */
clipToOutline = true clipToOutline = true
/** 设置一个圆角轮廓裁切 */ /** 设置一个圆角轮廓裁切 */
@@ -525,28 +537,13 @@ object SystemUIHooker : YukiBaseHooker() {
/** 清除着色 */ /** 清除着色 */
colorFilter = null colorFilter = null
} }
}
/** 打印日志 */
printLogcat(tag = "NotifyIcon", iconView.context, packageName, isCustom = customPair.first != null, isGrayscaleIcon)
}
}
/** /** 注册 */
* 设置通知面板背景透明度 private fun register() {
* @param view 背景 View 实例 /** 解锁后重新刷新状态栏图标防止系统重新设置它 */
* @param drawable 背景实例 onAppLifecycle { registerReceiver(Intent.ACTION_USER_PRESENT) { _, _ -> if (isUsingCachingMethod) refreshStatusBarIcons() } }
*/ /** 刷新图标缓存 */
private fun modifyNotifyPanelAlpha(view: View?, drawable: Drawable?) { SystemUITool.Host.onRefreshSystemUI(param = this) { recachingPrefs(it) }
prefs.get(DataConst.ENABLE_NOTIFY_PANEL_ALPHA).also { isEnabled ->
/** 设置通知面板背景透明度 */
when {
isEnabled.not() -> drawable?.alpha = 255
view?.parent?.parent?.javaClass?.name?.contains(other = "ChildrenContainer") == true -> drawable?.alpha = 0
else -> drawable?.alpha = prefs.get(DataConst.NOTIFY_PANEL_ALPHA)
}
/** 移除阴影效果 */
if (isEnabled) view?.elevation = 0f
}
} }
/** 缓存图标数据 */ /** 缓存图标数据 */
@@ -563,17 +560,25 @@ object SystemUIHooker : YukiBaseHooker() {
/** /**
* 刷新缓存数据 * 刷新缓存数据
* @param isRefreshCacheOnly 仅刷新缓存不刷新图标和通知改变 - 默认:否 * @param isRefreshCacheOnly 仅刷新缓存不刷新图标和通知改变 - 默认:否
* @return [Boolean] 是否成功
*/ */
private fun recachingPrefs(isRefreshCacheOnly: Boolean = false) { private fun recachingPrefs(isRefreshCacheOnly: Boolean = false): Boolean {
/** 必要的延迟防止 Sp 存储不刷新 */
SystemClock.sleep(100)
/** 获取可读写状态 */
return prefs.isXSharePrefsReadable.also {
isUsingCachingMethod = true isUsingCachingMethod = true
prefs.clearCache() prefs.clearCache()
cachingIconDatas() cachingIconDatas()
if (isRefreshCacheOnly) return if (isRefreshCacheOnly) return@also
refreshStatusBarIcons() refreshStatusBarIcons()
refreshNotificationIcons() refreshNotificationIcons()
} }
}
override fun onHook() { override fun onHook() {
/** 注册 */
register()
/** 缓存图标数据 */ /** 缓存图标数据 */
cachingIconDatas() cachingIconDatas()
/** 移除开发者警告通知 */ /** 移除开发者警告通知 */
@@ -666,12 +671,8 @@ object SystemUIHooker : YukiBaseHooker() {
param(StatusBarNotificationClass) param(StatusBarNotificationClass)
} }
afterHook { afterHook {
if (args().first().any() != null) instance<ImageView>().also {
/** 注册壁纸颜色监听 */ /** 注册壁纸颜色监听 */
registerWallpaperColorChanged(it) if (args().first().any() != null) instance<ImageView>().also { registerWallpaperColorChanged(it) }
/** 注册广播 */
registerReceiver(it.context)
}
} }
} }
} }
@@ -757,6 +758,47 @@ object SystemUIHooker : YukiBaseHooker() {
} }
} }
} }
/** 替换媒体通知面板背景 - 设置媒体通知自动展开 */
OplusMediaControlPanelClass.hook {
injectMember {
method {
name = "bind"
paramCount = 2
}
afterHook {
/** 得到当前实例 */
val holder = field {
name = "mViewHolder"
superClass(isOnlySuperClass = true)
}.get(instance).any()
/** 记录媒体通知 [View] */
notificationPlayerView = PlayerViewHolderClass.clazz.method {
name = "getPlayer"
emptyParam()
}.get(holder).invoke()
/** 设置背景着色 */
modifyNotifyPanelAlpha(notificationPlayerView, isTint = true)
/** 当前是否正在播放 */
val isPlaying = MediaDataClass.clazz.method {
name = "isPlaying"
emptyParam()
}.get(args().first().any()).boolean()
/** 当前通知是否展开 */
val isExpanded = OplusMediaViewControllerClass.clazz.method {
name = "getExpanded"
emptyParam()
}.get(field { name = "mOplusMediaViewController" }.get(instance).self).boolean()
/** 符合条件后执行 */
if (prefs.get(DataConst.ENABLE_NOTIFY_MEDIA_PANEL_AUTO_EXP).not() || isExpanded || isPlaying.not()) return@afterHook
/** 模拟手动展开通知 */
BasePlayViewHolderClass.clazz.method {
name = "getExpandButton"
emptyParam()
}.get(holder).invoke<View>()?.performClick()
}
}
}.ignoredHookClassNotFoundFailure()
/** 替换通知图标和样式 */ /** 替换通知图标和样式 */
NotificationHeaderViewWrapperClass.hook { NotificationHeaderViewWrapperClass.hook {
injectMember { injectMember {
@@ -830,8 +872,6 @@ object SystemUIHooker : YukiBaseHooker() {
} }
afterHook { afterHook {
args().first().cast<Context>()?.also { args().first().cast<Context>()?.also {
/** 注册广播 */
registerReceiver(it)
/** 注册定时监听 */ /** 注册定时监听 */
if (isEnableHookColorNotifyIcon() && prefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_AUTO)) if (isEnableHookColorNotifyIcon() && prefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_AUTO))
IconAdaptationTool.prepareAutoUpdateIconRule( IconAdaptationTool.prepareAutoUpdateIconRule(

View File

@@ -43,7 +43,7 @@ import com.fankes.coloros.notify.ui.activity.base.BaseActivity
import com.fankes.coloros.notify.utils.factory.* import com.fankes.coloros.notify.utils.factory.*
import com.fankes.coloros.notify.utils.tool.IconRuleManagerTool import com.fankes.coloros.notify.utils.tool.IconRuleManagerTool
import com.fankes.coloros.notify.utils.tool.SystemUITool import com.fankes.coloros.notify.utils.tool.SystemUITool
import com.highcapable.yukihookapi.hook.factory.isXposedModuleActive import com.highcapable.yukihookapi.YukiHookAPI
class ConfigureActivity : BaseActivity<ActivityConfigBinding>() { class ConfigureActivity : BaseActivity<ActivityConfigBinding>() {
@@ -61,7 +61,7 @@ class ConfigureActivity : BaseActivity<ActivityConfigBinding>() {
override fun onCreate() { override fun onCreate() {
/** 检查激活状态 */ /** 检查激活状态 */
if (isXposedModuleActive.not()) { if (YukiHookAPI.Status.isXposedModuleActive.not()) {
showDialog { showDialog {
title = "模块没有激活" title = "模块没有激活"
msg = "模块没有激活,你无法使用这里的功能,请先激活模块。" msg = "模块没有激活,你无法使用这里的功能,请先激活模块。"
@@ -154,9 +154,20 @@ class ConfigureActivity : BaseActivity<ActivityConfigBinding>() {
holder.adpAppAllSwitch.isChecked = isAppNotifyHookAllOf(it) holder.adpAppAllSwitch.isChecked = isAppNotifyHookAllOf(it)
holder.adpAppAllSwitch.setOnCheckedChangeListener { btn, b -> holder.adpAppAllSwitch.setOnCheckedChangeListener { btn, b ->
if (btn.isPressed.not()) return@setOnCheckedChangeListener if (btn.isPressed.not()) return@setOnCheckedChangeListener
fun saveState() {
putAppNotifyHookAllOf(it, b) putAppNotifyHookAllOf(it, b)
SystemUITool.refreshSystemUI(context = this@ConfigureActivity) SystemUITool.refreshSystemUI(context = this@ConfigureActivity)
} }
if (b) showDialog {
title = "全部替换"
msg = "此功能仅针对严重不遵守规范的 APP 通知图标才需要开启例如APP 推送通知后无法识别出现的黑白块图标。\n\n" +
"此功能在一般情况下请保持关闭并跟随在线规则的配置,并不要随意改变此配置," +
"开启后 APP 的通知图标可能会被规则破坏,你确定还要开启吗?"
confirmButton { saveState() }
cancelButton { btn.isChecked = btn.isChecked.not() }
noCancelable()
} else saveState()
}
} }
return cView!! return cView!!
} }
@@ -176,7 +187,13 @@ class ConfigureActivity : BaseActivity<ActivityConfigBinding>() {
} }
/** 设置点击事件 */ /** 设置点击事件 */
binding.configCbrButton.setOnClickListener { binding.configCbrButton.setOnClickListener {
openBrowser(url = "https://github.com/fankes/AndroidNotifyIconAdapt/blob/main/CONTRIBUTING.md") showDialog {
title = "感谢你的贡献"
msg = "通知图标优化名单需要大家的共同维护才能得以完善,请选择你的贡献方式。"
confirmButton(text = "贡献规则") { openBrowser(url = "https://github.com/fankes/AndroidNotifyIconAdapt/blob/main/CONTRIBUTING.md") }
cancelButton(text = "请求适配") { openBrowser(url = "https://github.com/fankes/ColorOSNotifyIcon/issues/new/choose") }
neutralButton(text = "暂时不用")
}
} }
/** 装载数据 */ /** 装载数据 */
mockLocalData() mockLocalData()

View File

@@ -38,9 +38,9 @@ import com.fankes.coloros.notify.ui.activity.base.BaseActivity
import com.fankes.coloros.notify.utils.factory.* import com.fankes.coloros.notify.utils.factory.*
import com.fankes.coloros.notify.utils.tool.GithubReleaseTool import com.fankes.coloros.notify.utils.tool.GithubReleaseTool
import com.fankes.coloros.notify.utils.tool.SystemUITool import com.fankes.coloros.notify.utils.tool.SystemUITool
import com.highcapable.yukihookapi.hook.factory.isXposedModuleActive import com.fankes.coloros.notify.utils.tool.YukiPromoteTool
import com.highcapable.yukihookapi.YukiHookAPI
import com.highcapable.yukihookapi.hook.factory.modulePrefs import com.highcapable.yukihookapi.hook.factory.modulePrefs
import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus
class MainActivity : BaseActivity<ActivityMainBinding>() { class MainActivity : BaseActivity<ActivityMainBinding>() {
@@ -87,7 +87,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
noCancelable() noCancelable()
} }
/** 判断是否 Hook */ /** 判断是否 Hook */
isXposedModuleActive -> { YukiHookAPI.Status.isXposedModuleActive -> {
if (IconPackParams(context = this).iconDatas.isEmpty() && modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX)) if (IconPackParams(context = this).iconDatas.isEmpty() && modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX))
showDialog { showDialog {
title = "配置通知图标优化名单" title = "配置通知图标优化名单"
@@ -105,6 +105,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
cancelButton() cancelButton()
noCancelable() noCancelable()
} }
/** 推广、恰饭 */
YukiPromoteTool.promote(context = this)
} }
else -> else ->
showDialog { showDialog {
@@ -122,25 +124,38 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
binding.a12StyleConfigItem.isVisible = modulePrefs.get(DataConst.ENABLE_MODULE) binding.a12StyleConfigItem.isVisible = modulePrefs.get(DataConst.ENABLE_MODULE)
binding.notifyIconConfigItem.isVisible = modulePrefs.get(DataConst.ENABLE_MODULE) binding.notifyIconConfigItem.isVisible = modulePrefs.get(DataConst.ENABLE_MODULE)
binding.notifyIconFixButton.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX) binding.notifyIconFixButton.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX)
binding.notifyIconCustomCornerItem.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX) &&
modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FORCE_APP_ICON).not()
binding.notifyIconForceAppIconItem.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX)
binding.notifyIconFixNotifyItem.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX) binding.notifyIconFixNotifyItem.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX)
binding.notifyIconAutoSyncItem.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX) binding.notifyIconAutoSyncItem.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX)
binding.notifyIconAutoSyncChildItem.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_AUTO) binding.notifyIconAutoSyncChildItem.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_AUTO)
binding.notifyPanelConfigSeekbar.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_PANEL_ALPHA) binding.notifyPanelConfigSeekbar.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_PANEL_ALPHA)
binding.notifyPanelConfigTextPanel.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_PANEL_ALPHA) binding.notifyPanelConfigTextPanel.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_PANEL_ALPHA)
binding.notifyPanelConfigWarnPanel.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_PANEL_ALPHA)
binding.devNotifyConfigSwitch.isChecked = modulePrefs.get(DataConst.REMOVE_DEV_NOTIFY) binding.devNotifyConfigSwitch.isChecked = modulePrefs.get(DataConst.REMOVE_DEV_NOTIFY)
binding.crcpNotifyConfigSwitch.isChecked = modulePrefs.get(DataConst.REMOVE_CHANGECP_NOTIFY) binding.crcpNotifyConfigSwitch.isChecked = modulePrefs.get(DataConst.REMOVE_CHANGECP_NOTIFY)
binding.dndNotifyConfigSwitch.isChecked = modulePrefs.get(DataConst.REMOVE_DNDALERT_NOTIFY) binding.dndNotifyConfigSwitch.isChecked = modulePrefs.get(DataConst.REMOVE_DNDALERT_NOTIFY)
binding.a12StyleConfigSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_ANDROID12_STYLE) binding.a12StyleConfigSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_ANDROID12_STYLE)
binding.notifyMediaPanelAutoExpSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_MEDIA_PANEL_AUTO_EXP)
binding.moduleEnableSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_MODULE) binding.moduleEnableSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_MODULE)
binding.moduleEnableLogSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_MODULE_LOG) binding.moduleEnableLogSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_MODULE_LOG)
binding.hideIconInLauncherSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_HIDE_ICON) binding.hideIconInLauncherSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_HIDE_ICON)
binding.notifyIconFixSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX) binding.notifyIconFixSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX)
binding.notifyIconForceAppIconSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FORCE_APP_ICON)
binding.notifyIconFixNotifySwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_NOTIFY) binding.notifyIconFixNotifySwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_NOTIFY)
binding.notifyIconAutoSyncSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_AUTO) binding.notifyIconAutoSyncSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_AUTO)
binding.notifyPanelConfigSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_PANEL_ALPHA) binding.notifyPanelConfigSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_PANEL_ALPHA)
binding.notifyPanelConfigSeekbar.progress = modulePrefs.get(DataConst.NOTIFY_PANEL_ALPHA) binding.notifyPanelConfigSeekbar.progress = modulePrefs.get(DataConst.NOTIFY_PANEL_ALPHA)
binding.notifyPanelConfigText.text = modulePrefs.get(DataConst.NOTIFY_PANEL_ALPHA).toString() binding.notifyIconCustomCornerSeekbar.progress = modulePrefs.get(DataConst.NOTIFY_ICON_CORNER)
binding.notifyPanelConfigText.text = "${modulePrefs.get(DataConst.NOTIFY_PANEL_ALPHA)}%"
binding.notifyIconCustomCornerText.text = "${modulePrefs.get(DataConst.NOTIFY_ICON_CORNER)} dp"
binding.notifyIconAutoSyncText.text = notifyIconAutoSyncTime binding.notifyIconAutoSyncText.text = notifyIconAutoSyncTime
/** 媒体通知自动展开仅支持 12.1 - 旧版本适配过于复杂已放弃 */
if (colorOSNumberVersion != "V12.1") {
binding.notifyMediaPanelAutoExpSwitch.isVisible = false
binding.notifyMediaPanelAutoExpText.isVisible = false
}
binding.moduleEnableSwitch.setOnCheckedChangeListener { btn, b -> binding.moduleEnableSwitch.setOnCheckedChangeListener { btn, b ->
if (btn.isPressed.not()) return@setOnCheckedChangeListener if (btn.isPressed.not()) return@setOnCheckedChangeListener
modulePrefs.put(DataConst.ENABLE_MODULE, b) modulePrefs.put(DataConst.ENABLE_MODULE, b)
@@ -168,10 +183,29 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
if (btn.isPressed.not()) return@setOnCheckedChangeListener if (btn.isPressed.not()) return@setOnCheckedChangeListener
modulePrefs.put(DataConst.ENABLE_NOTIFY_ICON_FIX, b) modulePrefs.put(DataConst.ENABLE_NOTIFY_ICON_FIX, b)
binding.notifyIconFixButton.isVisible = b binding.notifyIconFixButton.isVisible = b
binding.notifyIconCustomCornerItem.isVisible = b && modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FORCE_APP_ICON).not()
binding.notifyIconForceAppIconItem.isVisible = b
binding.notifyIconFixNotifyItem.isVisible = b binding.notifyIconFixNotifyItem.isVisible = b
binding.notifyIconAutoSyncItem.isVisible = b binding.notifyIconAutoSyncItem.isVisible = b
SystemUITool.refreshSystemUI(context = this) SystemUITool.refreshSystemUI(context = this)
} }
binding.notifyIconForceAppIconSwitch.setOnCheckedChangeListener { btn, b ->
if (btn.isPressed.not()) return@setOnCheckedChangeListener
fun saveState() {
binding.notifyIconCustomCornerItem.isVisible = b.not()
modulePrefs.put(DataConst.ENABLE_NOTIFY_ICON_FORCE_APP_ICON, b)
SystemUITool.refreshSystemUI(context = this)
}
if (b) showDialog {
title = "破坏性功能警告"
msg = "开启这个功能后,任何通知栏中的通知图标都会被强制替换为当前推送通知的 APP 的图标," +
"某些系统级别的 APP 通知图标可能会显示异常或发生图标丢失。\n\n" +
"此功能仅面向一些追求图标美观度的用户,我们不推荐开启这个功能,且发生任何 BUG 都不会去修复,仍然继续开启吗?"
confirmButton { saveState() }
cancelButton { btn.isChecked = btn.isChecked.not() }
noCancelable()
} else saveState()
}
binding.notifyIconFixNotifySwitch.setOnCheckedChangeListener { btn, b -> binding.notifyIconFixNotifySwitch.setOnCheckedChangeListener { btn, b ->
if (btn.isPressed.not()) return@setOnCheckedChangeListener if (btn.isPressed.not()) return@setOnCheckedChangeListener
modulePrefs.put(DataConst.ENABLE_NOTIFY_ICON_FIX_NOTIFY, b) modulePrefs.put(DataConst.ENABLE_NOTIFY_ICON_FIX_NOTIFY, b)
@@ -197,10 +231,16 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
modulePrefs.put(DataConst.ENABLE_ANDROID12_STYLE, b) modulePrefs.put(DataConst.ENABLE_ANDROID12_STYLE, b)
SystemUITool.refreshSystemUI(context = this) SystemUITool.refreshSystemUI(context = this)
} }
binding.notifyMediaPanelAutoExpSwitch.setOnCheckedChangeListener { btn, b ->
if (btn.isPressed.not()) return@setOnCheckedChangeListener
modulePrefs.put(DataConst.ENABLE_NOTIFY_MEDIA_PANEL_AUTO_EXP, b)
SystemUITool.refreshSystemUI(context = this, isRefreshCacheOnly = true)
}
binding.notifyPanelConfigSwitch.setOnCheckedChangeListener { btn, b -> binding.notifyPanelConfigSwitch.setOnCheckedChangeListener { btn, b ->
if (btn.isPressed.not()) return@setOnCheckedChangeListener if (btn.isPressed.not()) return@setOnCheckedChangeListener
modulePrefs.put(DataConst.ENABLE_NOTIFY_PANEL_ALPHA, b) modulePrefs.put(DataConst.ENABLE_NOTIFY_PANEL_ALPHA, b)
binding.notifyPanelConfigTextPanel.isVisible = b binding.notifyPanelConfigTextPanel.isVisible = b
binding.notifyPanelConfigWarnPanel.isVisible = b
binding.notifyPanelConfigSeekbar.isVisible = b binding.notifyPanelConfigSeekbar.isVisible = b
SystemUITool.refreshSystemUI(context = this) SystemUITool.refreshSystemUI(context = this)
} }
@@ -212,7 +252,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
} }
binding.notifyPanelConfigSeekbar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener { binding.notifyPanelConfigSeekbar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
binding.notifyPanelConfigText.text = progress.toString() binding.notifyPanelConfigText.text = "$progress%"
} }
override fun onStopTrackingTouch(seekBar: SeekBar) { override fun onStopTrackingTouch(seekBar: SeekBar) {
@@ -222,6 +262,18 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
override fun onStartTrackingTouch(seekBar: SeekBar?) {} override fun onStartTrackingTouch(seekBar: SeekBar?) {}
}) })
binding.notifyIconCustomCornerSeekbar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
binding.notifyIconCustomCornerText.text = "$progress dp"
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
modulePrefs.put(DataConst.NOTIFY_ICON_CORNER, seekBar.progress)
SystemUITool.refreshSystemUI(context = this@MainActivity)
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
})
/** 通知图标优化名单按钮点击事件 */ /** 通知图标优化名单按钮点击事件 */
binding.notifyIconFixButton.setOnClickListener { navigate<ConfigureActivity>() } binding.notifyIconFixButton.setOnClickListener { navigate<ConfigureActivity>() }
/** 自动更新在线规则修改时间按钮点击事件 */ /** 自动更新在线规则修改时间按钮点击事件 */
@@ -260,36 +312,36 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
private fun refreshModuleStatus() { private fun refreshModuleStatus() {
binding.mainLinStatus.setBackgroundResource( binding.mainLinStatus.setBackgroundResource(
when { when {
isXposedModuleActive && (isModuleRegular.not() || isModuleValied.not()) -> R.drawable.bg_yellow_round YukiHookAPI.Status.isXposedModuleActive && (isModuleRegular.not() || isModuleValied.not()) -> R.drawable.bg_yellow_round
isXposedModuleActive -> R.drawable.bg_green_round YukiHookAPI.Status.isXposedModuleActive -> R.drawable.bg_green_round
else -> R.drawable.bg_dark_round else -> R.drawable.bg_dark_round
} }
) )
binding.mainImgStatus.setImageResource( binding.mainImgStatus.setImageResource(
when { when {
isXposedModuleActive -> R.mipmap.ic_success YukiHookAPI.Status.isXposedModuleActive -> R.mipmap.ic_success
else -> R.mipmap.ic_warn else -> R.mipmap.ic_warn
} }
) )
binding.mainTextStatus.text = binding.mainTextStatus.text =
when { when {
isXposedModuleActive && isModuleRegular.not() && modulePrefs.get(DataConst.ENABLE_MODULE).not() -> "模块已停用" YukiHookAPI.Status.isXposedModuleActive && isModuleRegular.not() && modulePrefs.get(DataConst.ENABLE_MODULE).not() -> "模块已停用"
isXposedModuleActive && isModuleRegular.not() -> "模块已激活,请重启系统界面" YukiHookAPI.Status.isXposedModuleActive && isModuleRegular.not() -> "模块已激活,请重启系统界面"
isXposedModuleActive && isModuleValied.not() -> "模块已更新,请重启系统界面" YukiHookAPI.Status.isXposedModuleActive && isModuleValied.not() -> "模块已更新,请重启系统界面"
isXposedModuleActive -> "模块已激活" YukiHookAPI.Status.isXposedModuleActive -> "模块已激活"
else -> "模块未激活" else -> "模块未激活"
} }
binding.mainTextApiWay.isVisible = isXposedModuleActive binding.mainTextApiWay.isVisible = YukiHookAPI.Status.isXposedModuleActive
binding.mainTextApiWay.text = "Activated by ${YukiHookModuleStatus.executorName} API ${YukiHookModuleStatus.executorVersion}" binding.mainTextApiWay.text = "Activated by ${YukiHookAPI.Status.executorName} API ${YukiHookAPI.Status.executorVersion}"
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
/** 刷新模块状态 */ /** 刷新模块状态 */
refreshModuleStatus() refreshModuleStatus()
/** 发送广播检查模块激活状态 */ /** 检查模块激活状态 */
SystemUITool.checkingActivated(context = this) { isRegular, isValied -> SystemUITool.checkingActivated(context = this) { isValied ->
isModuleRegular = isRegular isModuleRegular = true
isModuleValied = isValied isModuleValied = isValied
refreshModuleStatus() refreshModuleStatus()
} }

View File

@@ -43,8 +43,6 @@ class NotifyIconRuleUpdateActivity : Activity() {
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
window?.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) window?.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
window?.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) window?.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
/** 注册 */
SystemUITool.register(context = this)
/** 检测运行状态 */ /** 检测运行状态 */
if (BaseActivity.isMainThreadRunning) { if (BaseActivity.isMainThreadRunning) {
finish() finish()
@@ -60,10 +58,4 @@ class NotifyIconRuleUpdateActivity : Activity() {
/** 切换到后台 */ /** 切换到后台 */
moveTaskToBack(true) moveTaskToBack(true)
} }
override fun onDestroy() {
super.onDestroy()
/** 解除注册 */
SystemUITool.unregister(context = this)
}
} }

View File

@@ -26,11 +26,11 @@ package com.fankes.coloros.notify.ui.activity.base
import android.os.Bundle import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.res.ResourcesCompat
import androidx.core.view.ViewCompat
import androidx.viewbinding.ViewBinding import androidx.viewbinding.ViewBinding
import com.fankes.coloros.notify.R import com.fankes.coloros.notify.R
import com.fankes.coloros.notify.utils.factory.isNotSystemInDarkMode import com.fankes.coloros.notify.utils.factory.isNotSystemInDarkMode
import com.fankes.coloros.notify.utils.tool.SystemUITool
import com.gyf.immersionbar.ktx.immersionBar
import com.highcapable.yukihookapi.hook.factory.method import com.highcapable.yukihookapi.hook.factory.method
import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass
import java.lang.reflect.ParameterizedType import java.lang.reflect.ParameterizedType
@@ -61,26 +61,19 @@ abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
/** 隐藏系统的标题栏 */ /** 隐藏系统的标题栏 */
supportActionBar?.hide() supportActionBar?.hide()
/** 初始化沉浸状态栏 */ /** 初始化沉浸状态栏 */
immersionBar { ViewCompat.getWindowInsetsController(window.decorView)?.apply {
statusBarColor(R.color.colorThemeBackground) isAppearanceLightStatusBars = isNotSystemInDarkMode
autoDarkModeEnable(true) isAppearanceLightNavigationBars = isNotSystemInDarkMode
statusBarDarkFont(isNotSystemInDarkMode) }
navigationBarColor(R.color.colorThemeBackground) ResourcesCompat.getColor(resources, R.color.colorThemeBackground, null).also {
navigationBarDarkIcon(isNotSystemInDarkMode) window?.statusBarColor = it
fitsSystemWindows(true) window?.navigationBarColor = it
window?.navigationBarDividerColor = it
} }
/** 注册 */
SystemUITool.register(context = this)
/** 装载子类 */ /** 装载子类 */
onCreate() onCreate()
} }
/** 回调 [onCreate] 方法 */ /** 回调 [onCreate] 方法 */
abstract fun onCreate() abstract fun onCreate()
override fun onDestroy() {
super.onDestroy()
/** 解除注册 */
SystemUITool.unregister(context = this)
}
} }

View File

@@ -46,18 +46,18 @@ import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass
/** /**
* 构造对话框 * 构造对话框
* @param isUseBlackTheme 是否使用深色主题 * @param isUseBlackTheme 是否使用深色主题
* @param it 对话框方法体 * @param initiate 对话框方法体
*/ */
fun Context.showDialog(isUseBlackTheme: Boolean = false, it: DialogBuilder.() -> Unit) = fun Context.showDialog(isUseBlackTheme: Boolean = false, initiate: DialogBuilder.() -> Unit) =
DialogBuilder(this, isUseBlackTheme).apply(it).show() DialogBuilder(context = this, isUseBlackTheme).apply(initiate).show()
/** /**
* 显示时间选择对话框 * 显示时间选择对话框
* @param timeSet 当前时间 - 不写将使用当前时间格式HH:mm * @param timeSet 当前时间 - 不写将使用当前时间格式HH:mm
* @param it 回调 - 小时与分钟 HH:mm * @param result 回调 - 小时与分钟 HH:mm
*/ */
fun Context.showTimePicker(timeSet: String = "", it: (String) -> Unit) = fun Context.showTimePicker(timeSet: String = "", result: (String) -> Unit) =
TimePickerDialog(this, { _, h, m -> it("${h.autoZero}:${m.autoZero}") }, timeSet.hour, timeSet.minute, true).show() TimePickerDialog(this, { _, h, m -> result("${h.autoZero}:${m.autoZero}") }, timeSet.hour, timeSet.minute, true).show()
/** /**
* 对话框构造器 * 对话框构造器
@@ -150,34 +150,34 @@ class DialogBuilder(val context: Context, private val isUseBlackTheme: Boolean)
/** /**
* 设置对话框确定按钮 * 设置对话框确定按钮
* @param text 按钮文本内容 * @param text 按钮文本内容
* @param it 点击事件 * @param callback 点击事件
*/ */
fun confirmButton(text: String = "确定", it: () -> Unit = {}) { fun confirmButton(text: String = "确定", callback: () -> Unit = {}) {
if (isUsingAndroidX) if (isUsingAndroidX)
runInSafe { instanceAndroidX?.setPositiveButton(text) { _, _ -> it() } } runInSafe { instanceAndroidX?.setPositiveButton(text) { _, _ -> callback() } }
else runInSafe { instanceAndroid?.setPositiveButton(text) { _, _ -> it() } } else runInSafe { instanceAndroid?.setPositiveButton(text) { _, _ -> callback() } }
} }
/** /**
* 设置对话框取消按钮 * 设置对话框取消按钮
* @param text 按钮文本内容 * @param text 按钮文本内容
* @param it 点击事件 * @param callback 点击事件
*/ */
fun cancelButton(text: String = "取消", it: () -> Unit = {}) { fun cancelButton(text: String = "取消", callback: () -> Unit = {}) {
if (isUsingAndroidX) if (isUsingAndroidX)
runInSafe { instanceAndroidX?.setNegativeButton(text) { _, _ -> it() } } runInSafe { instanceAndroidX?.setNegativeButton(text) { _, _ -> callback() } }
else runInSafe { instanceAndroid?.setNegativeButton(text) { _, _ -> it() } } else runInSafe { instanceAndroid?.setNegativeButton(text) { _, _ -> callback() } }
} }
/** /**
* 设置对话框第三个按钮 * 设置对话框第三个按钮
* @param text 按钮文本内容 * @param text 按钮文本内容
* @param it 点击事件 * @param callback 点击事件
*/ */
fun neutralButton(text: String = "更多", it: () -> Unit = {}) { fun neutralButton(text: String = "更多", callback: () -> Unit = {}) {
if (isUsingAndroidX) if (isUsingAndroidX)
runInSafe { instanceAndroidX?.setNeutralButton(text) { _, _ -> it() } } runInSafe { instanceAndroidX?.setNeutralButton(text) { _, _ -> callback() } }
else runInSafe { instanceAndroid?.setNeutralButton(text) { _, _ -> it() } } else runInSafe { instanceAndroid?.setNeutralButton(text) { _, _ -> callback() } }
} }
/** 取消对话框 */ /** 取消对话框 */

View File

@@ -138,14 +138,20 @@ val colorOSFullVersion get() = "${if (isRealmeUI) "RealmeUI " else ""}$colorOSVe
* 获取 ColorOS 版本 * 获取 ColorOS 版本
* @return [String] * @return [String]
*/ */
val colorOSVersion val colorOSVersion get() = "$colorOSNumberVersion ${Build.DISPLAY}"
/**
* 获取 ColorOS 数字版本
* @return [String]
*/
val colorOSNumberVersion
get() = safeOf(default = "无法获取") { get() = safeOf(default = "无法获取") {
(classOf(name = "com.oplus.os.OplusBuild").let { (classOf(name = "com.oplus.os.OplusBuild").let {
it.field { name = "VERSIONS" }.ignoredError().get().array<String>().takeIf { e -> e.isNotEmpty() } it.field { name = "VERSIONS" }.ignoredError().get().array<String>().takeIf { e -> e.isNotEmpty() }
?.get(it.method { name = "getOplusOSVERSION" }.ignoredError().get().int() - 1) ?.get(it.method { name = "getOplusOSVERSION" }.ignoredError().get().int() - 1)
} ?: findPropString( } ?: findPropString(
key = "ro.system.build.fingerprint", default = "无法获取" key = "ro.system.build.fingerprint", default = "无法获取"
).split("ssi:")[1].split("/")[0].trim()) + " ${Build.DISPLAY}" ).split("ssi:")[1].split("/")[0].trim())
} }
/** /**
@@ -280,6 +286,13 @@ val Int.isWhite
(0.2126 * r + 0.7152 * g + 0.0722 * b) >= 128 (0.2126 * r + 0.7152 * g + 0.0722 * b) >= 128
} }
/**
* 调整颜色透明度
* @param value 透明度
* @return [Int] 调整后的颜色
*/
fun Int.colorAlphaOf(value: Float) = safeOfNan { (255.coerceAtMost(0.coerceAtLeast((value * 255).toInt())) shl 24) + (0x00ffffff and this) }
/** /**
* Base64 加密 * Base64 加密
* @return [String] * @return [String]
@@ -357,27 +370,23 @@ fun toast(msg: String) = Toast.makeText(appContext, msg, Toast.LENGTH_SHORT).sho
* *
* [T] 为指定的 [Activity] * [T] 为指定的 [Activity]
*/ */
inline fun <reified T : Activity> Context.navigate() = runInSafe { startActivity(Intent(this, T::class.java)) } inline fun <reified T : Activity> Context.navigate() = runInSafe {
startActivity(Intent(if (this is Service) applicationContext else this, T::class.java).apply {
/** if (this@navigate !is Activity) flags = Intent.FLAG_ACTIVITY_NEW_TASK
* 跳转到指定页面 })
* }
* [T] 为指定的 [Activity]
*/
inline fun <reified T : Activity> Service.navigate() =
runInSafe { startActivity(Intent(this, T::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK }) }
/** /**
* 弹出 [Snackbar] * 弹出 [Snackbar]
* @param msg 提示内容 * @param msg 提示内容
* @param actionText 按钮文本 - 不写默认取消按钮 * @param actionText 按钮文本 - 不写默认取消按钮
* @param it 按钮事件回调 * @param callback 按钮事件回调
*/ */
fun Context.snake(msg: String, actionText: String = "", it: () -> Unit = {}) = fun Context.snake(msg: String, actionText: String = "", callback: () -> Unit = {}) =
Snackbar.make((this as Activity).findViewById(android.R.id.content), msg, Snackbar.LENGTH_LONG).apply { Snackbar.make((this as Activity).findViewById(android.R.id.content), msg, Snackbar.LENGTH_LONG).apply {
if (actionText.isBlank()) return@apply if (actionText.isBlank()) return@apply
setActionTextColor(if (isSystemInDarkMode) Color.BLACK else Color.WHITE) setActionTextColor(if (isSystemInDarkMode) Color.BLACK else Color.WHITE)
setAction(actionText) { it() } setAction(actionText) { callback() }
}.show() }.show()
/** /**

View File

@@ -45,9 +45,9 @@ object GithubReleaseTool {
* 获取最新版本信息 * 获取最新版本信息
* @param context 实例 * @param context 实例
* @param version 当前版本 * @param version 当前版本
* @param it 成功后回调 - ([String] 最新版本,[Function] 更新对话框方法体) * @param result 成功后回调 - ([String] 最新版本,[Function] 更新对话框方法体)
*/ */
fun checkingForUpdate(context: Context, version: String, it: (String, () -> Unit) -> Unit) = checkingInternetConnect(context) { fun checkingForUpdate(context: Context, version: String, result: (String, () -> Unit) -> Unit) = checkingInternetConnect(context) {
OkHttpClient().newBuilder().build().newCall( OkHttpClient().newBuilder().build().newCall(
Request.Builder() Request.Builder()
.url("https://api.github.com/repos/$REPO_AUTHOR/$REPO_NAME/releases/latest") .url("https://api.github.com/repos/$REPO_AUTHOR/$REPO_NAME/releases/latest")
@@ -73,7 +73,7 @@ object GithubReleaseTool {
} }
if (name != version) (context as? Activity?)?.runOnUiThread { if (name != version) (context as? Activity?)?.runOnUiThread {
showUpdate() showUpdate()
it(name) { showUpdate() } result(name) { showUpdate() }
} }
} }
} }
@@ -84,9 +84,9 @@ object GithubReleaseTool {
/** /**
* 检查网络连接情况 * 检查网络连接情况
* @param context 实例 * @param context 实例
* @param it 已连接回调 * @param result 已连接回调
*/ */
private fun checkingInternetConnect(context: Context, it: () -> Unit) = runInSafe { private fun checkingInternetConnect(context: Context, result: () -> Unit) = runInSafe {
if (isNetWorkSuccess) if (isNetWorkSuccess)
OkHttpClient().newBuilder().build().newCall( OkHttpClient().newBuilder().build().newCall(
Request.Builder() Request.Builder()
@@ -107,7 +107,7 @@ object GithubReleaseTool {
} }
override fun onResponse(call: Call, response: Response) = runInSafe { override fun onResponse(call: Call, response: Response) = runInSafe {
(context as? Activity?)?.runOnUiThread { runInSafe { it() } } (context as? Activity?)?.runOnUiThread { runInSafe { result() } }
} }
}) })
} }

View File

@@ -33,7 +33,7 @@ import android.graphics.Bitmap
import android.graphics.drawable.Icon import android.graphics.drawable.Icon
import android.os.Build import android.os.Build
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import com.fankes.coloros.notify.const.Const import com.fankes.coloros.notify.BuildConfig
import com.fankes.coloros.notify.hook.HookEntry import com.fankes.coloros.notify.hook.HookEntry
import com.fankes.coloros.notify.utils.factory.* import com.fankes.coloros.notify.utils.factory.*
@@ -44,6 +44,9 @@ import com.fankes.coloros.notify.utils.factory.*
*/ */
object IconAdaptationTool { object IconAdaptationTool {
/** 当前模块的包名 */
private const val MODULE_PACKAGE_NAME = BuildConfig.APPLICATION_ID
/** 推送通知的渠道名称 */ /** 推送通知的渠道名称 */
private const val NOTIFY_CHANNEL = "notifyRuleSupportId" private const val NOTIFY_CHANNEL = "notifyRuleSupportId"
@@ -137,8 +140,8 @@ object IconAdaptationTool {
context, packageName.hashCode(), context, packageName.hashCode(),
Intent().apply { Intent().apply {
component = ComponentName( component = ComponentName(
Const.MODULE_PACKAGE_NAME, MODULE_PACKAGE_NAME,
"${Const.MODULE_PACKAGE_NAME}.ui.activity.ConfigureActivity" "${MODULE_PACKAGE_NAME}.ui.activity.ConfigureActivity"
) )
flags = Intent.FLAG_ACTIVITY_NEW_TASK flags = Intent.FLAG_ACTIVITY_NEW_TASK
}.apply { }.apply {
@@ -177,8 +180,8 @@ object IconAdaptationTool {
context.startActivity( context.startActivity(
Intent().apply { Intent().apply {
component = ComponentName( component = ComponentName(
Const.MODULE_PACKAGE_NAME, MODULE_PACKAGE_NAME,
"${Const.MODULE_PACKAGE_NAME}.ui.activity.auto.NotifyIconRuleUpdateActivity" "${MODULE_PACKAGE_NAME}.ui.activity.auto.NotifyIconRuleUpdateActivity"
) )
flags = Intent.FLAG_ACTIVITY_NEW_TASK flags = Intent.FLAG_ACTIVITY_NEW_TASK
} }

View File

@@ -75,9 +75,9 @@ object IconRuleManagerTool {
/** /**
* 从在线地址手动同步规则 * 从在线地址手动同步规则
* @param context 实例 * @param context 实例
* @param it 成功后回调 * @param callback 成功后回调
*/ */
fun syncByHand(context: Context, it: () -> Unit) = fun syncByHand(context: Context, callback: () -> Unit) =
context.showDialog { context.showDialog {
title = "同步列表" title = "同步列表"
var sourceType = context.modulePrefs.get(DataConst.SOURCE_SYNC_WAY) var sourceType = context.modulePrefs.get(DataConst.SOURCE_SYNC_WAY)
@@ -116,7 +116,7 @@ object IconRuleManagerTool {
confirmButton { confirmButton {
context.modulePrefs.put(DataConst.SOURCE_SYNC_WAY, sourceType) context.modulePrefs.put(DataConst.SOURCE_SYNC_WAY, sourceType)
context.modulePrefs.put(DataConst.SOURCE_SYNC_WAY_CUSTOM_URL, customUrl) context.modulePrefs.put(DataConst.SOURCE_SYNC_WAY_CUSTOM_URL, customUrl)
sync(context, sourceType, customUrl, it) sync(context, sourceType, customUrl, callback)
} }
cancelButton() cancelButton()
neutralButton(text = "自定义规则") { neutralButton(text = "自定义规则") {
@@ -139,7 +139,7 @@ object IconRuleManagerTool {
) )
) )
notifyRefresh(context) notifyRefresh(context)
it() callback()
} }
else -> context.snake(msg = "请输入有效内容") else -> context.snake(msg = "请输入有效内容")
} }
@@ -152,7 +152,7 @@ object IconRuleManagerTool {
jsonString.isNotBlank() -> { jsonString.isNotBlank() -> {
params.save(dataJson = jsonString.takeIf { params.isJsonArray(it) } ?: "[$jsonString]") params.save(dataJson = jsonString.takeIf { params.isJsonArray(it) } ?: "[$jsonString]")
notifyRefresh(context) notifyRefresh(context)
it() callback()
} }
else -> context.snake(msg = "请输入有效内容") else -> context.snake(msg = "请输入有效内容")
} }
@@ -169,23 +169,23 @@ object IconRuleManagerTool {
* @param context 实例 * @param context 实例
* @param sourceType 同步地址类型 - 默认自动获取已存储的键值 * @param sourceType 同步地址类型 - 默认自动获取已存储的键值
* @param customUrl 自定义同步地址 - 默认自动获取已存储的键值 * @param customUrl 自定义同步地址 - 默认自动获取已存储的键值
* @param it 成功后回调 * @param callback 成功后回调
*/ */
fun sync( fun sync(
context: Context, context: Context,
sourceType: Int = context.modulePrefs.get(DataConst.SOURCE_SYNC_WAY), sourceType: Int = context.modulePrefs.get(DataConst.SOURCE_SYNC_WAY),
customUrl: String = context.modulePrefs.get(DataConst.SOURCE_SYNC_WAY_CUSTOM_URL), customUrl: String = context.modulePrefs.get(DataConst.SOURCE_SYNC_WAY_CUSTOM_URL),
it: () -> Unit callback: () -> Unit
) { ) {
when (sourceType) { when (sourceType) {
TYPE_SOURCE_SYNC_WAY_1 -> TYPE_SOURCE_SYNC_WAY_1 ->
onRefreshing(context, url = "https://raw.fastgit.org/fankes/AndroidNotifyIconAdapt/main", it) onRefreshing(context, url = "https://raw.fastgit.org/fankes/AndroidNotifyIconAdapt/main", callback)
TYPE_SOURCE_SYNC_WAY_2 -> TYPE_SOURCE_SYNC_WAY_2 ->
onRefreshing(context, url = "https://raw.githubusercontent.com/fankes/AndroidNotifyIconAdapt/main", it) onRefreshing(context, url = "https://raw.githubusercontent.com/fankes/AndroidNotifyIconAdapt/main", callback)
TYPE_SOURCE_SYNC_WAY_3 -> TYPE_SOURCE_SYNC_WAY_3 ->
if (customUrl.isNotBlank()) if (customUrl.isNotBlank())
if (customUrl.startsWith("http://") || customUrl.startsWith("https://")) if (customUrl.startsWith("http://") || customUrl.startsWith("https://"))
onRefreshingCustom(context, customUrl, it) onRefreshingCustom(context, customUrl, callback)
else context.snakeOrNotify(title = "同步失败", msg = "同步地址不是一个合法的 URL") else context.snakeOrNotify(title = "同步失败", msg = "同步地址不是一个合法的 URL")
else context.snakeOrNotify(title = "同步失败", msg = "同步地址不能为空") else context.snakeOrNotify(title = "同步失败", msg = "同步地址不能为空")
else -> context.snakeOrNotify(title = "同步异常", msg = "同步类型错误") else -> context.snakeOrNotify(title = "同步异常", msg = "同步类型错误")
@@ -196,14 +196,14 @@ object IconRuleManagerTool {
* 开始更新数据 * 开始更新数据
* @param context 实例 * @param context 实例
* @param url * @param url
* @param it 成功后回调 * @param callback 成功后回调
*/ */
private fun onRefreshing(context: Context, url: String, it: () -> Unit) = checkingInternetConnect(context) { private fun onRefreshing(context: Context, url: String, callback: () -> Unit) = checkingInternetConnect(context) {
fun doParse(callback: (Boolean) -> Unit = {}) { fun doParse(result: (Boolean) -> Unit = {}) {
wait(context, url = "$url/OS/$OS_TAG/NotifyIconsSupportConfig.json") { isDone1, ctOS -> wait(context, url = "$url/OS/$OS_TAG/NotifyIconsSupportConfig.json") { isDone1, ctOS ->
callback(true) result(true)
wait(context, url = "$url/APP/NotifyIconsSupportConfig.json") { isDone2, ctAPP -> wait(context, url = "$url/APP/NotifyIconsSupportConfig.json") { isDone2, ctAPP ->
callback(false) result(false)
IconPackParams(context).also { params -> IconPackParams(context).also { params ->
when { when {
isDone1 && isDone2 -> params.splicingJsonArray(ctOS, ctAPP).also { isDone1 && isDone2 -> params.splicingJsonArray(ctOS, ctAPP).also {
@@ -216,7 +216,7 @@ object IconRuleManagerTool {
params.save(it) params.save(it)
pushNotify(context, title = "同步完成", msg = "已更新通知图标优化名单,点击查看") pushNotify(context, title = "同步完成", msg = "已更新通知图标优化名单,点击查看")
notifyRefresh(context) notifyRefresh(context)
it() callback()
} }
else -> (if (context is AppCompatActivity) context.snake(msg = "列表数据已是最新")) else -> (if (context is AppCompatActivity) context.snake(msg = "列表数据已是最新"))
} }
@@ -225,7 +225,7 @@ object IconRuleManagerTool {
context.showDialog { context.showDialog {
title = "连接失败" title = "连接失败"
msg = "连接失败,错误如下:\n${if (isDone1.not()) ctOS else ctAPP}" msg = "连接失败,错误如下:\n${if (isDone1.not()) ctOS else ctAPP}"
confirmButton(text = "再试一次") { syncByHand(context, it) } confirmButton(text = "再试一次") { syncByHand(context, callback) }
cancelButton() cancelButton()
} }
else -> pushNotify(context, title = "同步地址不可用", msg = if (isDone1.not()) ctOS else ctAPP) else -> pushNotify(context, title = "同步地址不可用", msg = if (isDone1.not()) ctOS else ctAPP)
@@ -248,12 +248,12 @@ object IconRuleManagerTool {
* 开始更新数据 * 开始更新数据
* @param context 实例 * @param context 实例
* @param url * @param url
* @param it 成功后回调 * @param callback 成功后回调
*/ */
private fun onRefreshingCustom(context: Context, url: String, it: () -> Unit) = checkingInternetConnect(context) { private fun onRefreshingCustom(context: Context, url: String, callback: () -> Unit) = checkingInternetConnect(context) {
fun doParse(callback: () -> Unit = {}) { fun doParse(result: () -> Unit = {}) {
wait(context, url) { isDone, content -> wait(context, url) { isDone, content ->
callback() result()
IconPackParams(context).also { params -> IconPackParams(context).also { params ->
when { when {
isDone -> when { isDone -> when {
@@ -265,7 +265,7 @@ object IconRuleManagerTool {
params.save(content) params.save(content)
pushNotify(context, title = "同步完成", msg = "已更新通知图标优化名单,点击查看") pushNotify(context, title = "同步完成", msg = "已更新通知图标优化名单,点击查看")
notifyRefresh(context) notifyRefresh(context)
it() callback()
} }
else -> (if (context is AppCompatActivity) context.snake(msg = "列表数据已是最新")) else -> (if (context is AppCompatActivity) context.snake(msg = "列表数据已是最新"))
} }
@@ -293,16 +293,16 @@ object IconRuleManagerTool {
/** /**
* 检查网络连接情况 * 检查网络连接情况
* @param context 实例 * @param context 实例
* @param it 已连接回调 * @param callback 已连接回调
*/ */
private fun checkingInternetConnect(context: Context, it: () -> Unit) = private fun checkingInternetConnect(context: Context, callback: () -> Unit) =
if (context is AppCompatActivity) context.showDialog { if (context is AppCompatActivity) context.showDialog {
title = "准备中" title = "准备中"
progressContent = "正在检查网络连接情况" progressContent = "正在检查网络连接情况"
noCancelable() noCancelable()
baseCheckingInternetConnect(context) { isDone -> baseCheckingInternetConnect(context) { isDone ->
cancel() cancel()
if (isDone) it() else if (isDone) callback() else
context.showDialog { context.showDialog {
title = "网络不可用" title = "网络不可用"
msg = "无法连接到互联网,请检查你当前的设备是否可以上网,且没有在手机管家中禁用本模块的联网权限。" msg = "无法连接到互联网,请检查你当前的设备是否可以上网,且没有在手机管家中禁用本模块的联网权限。"
@@ -319,24 +319,24 @@ object IconRuleManagerTool {
} }
} }
} else baseCheckingInternetConnect(context) { isDone -> } else baseCheckingInternetConnect(context) { isDone ->
if (isDone) it() else pushNotify(context, title = "网络不可用", msg = "无法连接到互联网,无法更新通知图标规则") if (isDone) callback() else pushNotify(context, title = "网络不可用", msg = "无法连接到互联网,无法更新通知图标规则")
} }
/** /**
* 检查网络连接情况 * 检查网络连接情况
* @param context 实例 * @param context 实例
* @param it 已连接回调 * @param result 已连接回调
*/ */
private fun baseCheckingInternetConnect(context: Context, it: (Boolean) -> Unit) = private fun baseCheckingInternetConnect(context: Context, result: (Boolean) -> Unit) =
wait(context, url = "https://www.baidu.com") { isDone, _ -> it(isDone) } wait(context, url = "https://www.baidu.com") { isDone, _ -> result(isDone) }
/** /**
* 发送 GET 请求内容并等待 * 发送 GET 请求内容并等待
* @param context 实例 * @param context 实例
* @param url 请求地址 * @param url 请求地址
* @param it 回调 - ([Boolean] 是否成功,[String] 成功的内容或失败消息) * @param result 回调 - ([Boolean] 是否成功,[String] 成功的内容或失败消息)
*/ */
private fun wait(context: Context, url: String, it: (Boolean, String) -> Unit) = runCatching { private fun wait(context: Context, url: String, result: (Boolean, String) -> Unit) = runCatching {
OkHttpClient().newBuilder().apply { OkHttpClient().newBuilder().apply {
SSLSocketClient.sSLSocketFactory?.let { sslSocketFactory(it, SSLSocketClient.trustManager) } SSLSocketClient.sSLSocketFactory?.let { sslSocketFactory(it, SSLSocketClient.trustManager) }
hostnameVerifier(SSLSocketClient.hostnameVerifier) hostnameVerifier(SSLSocketClient.hostnameVerifier)
@@ -347,15 +347,15 @@ object IconRuleManagerTool {
.build() .build()
).enqueue(object : Callback { ).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) { override fun onFailure(call: Call, e: IOException) {
(context as? Activity?)?.runOnUiThread { it(false, e.toString()) } ?: it(false, e.toString()) (context as? Activity?)?.runOnUiThread { result(false, e.toString()) } ?: result(false, e.toString())
} }
override fun onResponse(call: Call, response: Response) { override fun onResponse(call: Call, response: Response) {
val bodyString = response.body?.string() ?: "" val bodyString = response.body?.string() ?: ""
(context as? Activity?)?.runOnUiThread { it(true, bodyString) } ?: it(true, bodyString) (context as? Activity?)?.runOnUiThread { result(true, bodyString) } ?: result(true, bodyString)
} }
}) })
}.onFailure { it(false, "URL 无效") } }.onFailure { result(false, "URL 无效") }
/** /**
* 推送通知图标更新通知 * 推送通知图标更新通知

View File

@@ -22,59 +22,44 @@
*/ */
package com.fankes.coloros.notify.utils.tool package com.fankes.coloros.notify.utils.tool
import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import com.fankes.coloros.notify.hook.HookConst.SYSTEMUI_PACKAGE_NAME
import android.content.IntentFilter
import com.fankes.coloros.notify.const.Const
import com.fankes.coloros.notify.utils.factory.* import com.fankes.coloros.notify.utils.factory.*
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.highcapable.yukihookapi.hook.factory.isXposedModuleActive import com.highcapable.yukihookapi.YukiHookAPI
import com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication.Companion.appContext import com.highcapable.yukihookapi.hook.factory.dataChannel
import com.highcapable.yukihookapi.hook.param.PackageParam
import com.highcapable.yukihookapi.hook.xposed.channel.data.ChannelData
/** /**
* 系统界面工具 * 系统界面工具
*/ */
object SystemUITool { object SystemUITool {
/** 宿主广播回调 */ private val CALL_HOST_REFRESH_CACHING = ChannelData("call_host_refresh_caching", false)
private var moduleHandlerCallback: ((Boolean, Boolean) -> Unit)? = null private val CALL_MODULE_REFRESH_RESULT = ChannelData("call_module_refresh_result", false)
/** 通知广播回调 */
private var remindHandlerCallback: ((Boolean, Boolean) -> Unit)? = null
/** /**
* 注册广播 * 宿主注册监听
* @param context 实例
*/ */
fun register(context: Context) = runInSafe { object Host {
/** 注册广播检查模块激活状态 */
context.registerReceiver(moduleHandlerReceiver, IntentFilter().apply { addAction(Const.ACTION_MODULE_HANDLER_RECEIVER) }) /**
/** 注册广播通知系统界面改变 */ * 监听系统界面刷新改变
context.registerReceiver(remindHandlerReceiver, IntentFilter().apply { addAction(Const.ACTION_REMIND_HANDLER_RECEIVER) }) * @param param 实例
* @param result 回调 - ([Boolean] 是否成功)
*/
fun onRefreshSystemUI(param: PackageParam, result: (Boolean) -> Boolean) {
param.dataChannel.with { wait(CALL_HOST_REFRESH_CACHING) { put(CALL_MODULE_REFRESH_RESULT, result(it)) } }
} }
/**
* 取消注册广播
* @param context 实例
*/
fun unregister(context: Context) = runInSafe {
context.unregisterReceiver(moduleHandlerReceiver)
context.unregisterReceiver(remindHandlerReceiver)
} }
/** /**
* 检查模块是否激活 * 检查模块是否激活
* @param context 实例 * @param context 实例
* @param it 成功后回调 - ([Boolean] 是否激活,[Boolean] 是否有效) * @param result 成功后回调
*/ */
fun checkingActivated(context: Context, it: (Boolean, Boolean) -> Unit) { fun checkingActivated(context: Context, result: (Boolean) -> Unit) = context.dataChannel(SYSTEMUI_PACKAGE_NAME).checkingVersionEquals(result)
moduleHandlerCallback = it
context.sendBroadcast(Intent().apply {
action = Const.ACTION_MODULE_CHECKING_RECEIVER
putExtra(Const.MODULE_VERSION_VERIFY_TAG, Const.MODULE_VERSION_VERIFY)
})
}
/** /**
* 重启系统界面 * 重启系统界面
@@ -99,17 +84,10 @@ object SystemUITool {
* 刷新系统界面状态栏与通知图标 * 刷新系统界面状态栏与通知图标
* @param context 实例 * @param context 实例
* @param isRefreshCacheOnly 仅刷新缓存不刷新图标和通知改变 - 默认:否 * @param isRefreshCacheOnly 仅刷新缓存不刷新图标和通知改变 - 默认:否
* @param it 成功后回调 * @param callback 成功后回调
*/ */
fun refreshSystemUI(context: Context? = null, isRefreshCacheOnly: Boolean = false, it: () -> Unit = {}) = runInSafe { fun refreshSystemUI(context: Context? = null, isRefreshCacheOnly: Boolean = false, callback: () -> Unit = {}) = runInSafe {
fun sendMessage() { if (YukiHookAPI.Status.isXposedModuleActive)
(context ?: appContext).sendBroadcast(Intent().apply {
action = Const.ACTION_REMIND_CHECKING_RECEIVER
putExtra("isRefreshCacheOnly", isRefreshCacheOnly)
putExtra(Const.MODULE_VERSION_VERIFY_TAG, Const.MODULE_VERSION_VERIFY)
})
}
if (isXposedModuleActive)
context?.showDialog { context?.showDialog {
title = "请稍后" title = "请稍后"
progressContent = "正在等待系统界面刷新" progressContent = "正在等待系统界面刷新"
@@ -118,23 +96,29 @@ object SystemUITool {
/** 设置等待延迟 */ /** 设置等待延迟 */
delayedRun(ms = 5000) { delayedRun(ms = 5000) {
if (isWaited) return@delayedRun if (isWaited) return@delayedRun
remindHandlerCallback = null
cancel() cancel()
context.snake(msg = "预计响应超时,建议重启系统界面", actionText = "立即重启") { restartSystemUI(context) } context.snake(msg = "预计响应超时,建议重启系统界面", actionText = "立即重启") { restartSystemUI(context) }
} }
remindHandlerCallback = { isGrasp, isValied -> checkingActivated(context) { isValied ->
remindHandlerCallback = null when {
isValied.not() -> {
cancel() cancel()
isWaited = true isWaited = true
when {
isGrasp && !isValied ->
context.snake(msg = "请重启系统界面以生效模块更新", actionText = "立即重启") { restartSystemUI(context) } context.snake(msg = "请重启系统界面以生效模块更新", actionText = "立即重启") { restartSystemUI(context) }
else -> it() }
else -> context.dataChannel(SYSTEMUI_PACKAGE_NAME).with {
wait(CALL_MODULE_REFRESH_RESULT) {
cancel()
isWaited = true
callback()
if (it.not()) context.snake(msg = "刷新失败,建议重启系统界面", actionText = "立即重启") { restartSystemUI(context) }
}
put(CALL_HOST_REFRESH_CACHING, isRefreshCacheOnly)
}
} }
} }
sendMessage()
noCancelable() noCancelable()
} ?: sendMessage() }
else context?.snake(msg = "模块没有激活,更改不会生效") else context?.snake(msg = "模块没有激活,更改不会生效")
} }
@@ -143,29 +127,7 @@ object SystemUITool {
* @param context 实例 * @param context 实例
*/ */
fun showNeedRestartSnake(context: Context) = fun showNeedRestartSnake(context: Context) =
if (isXposedModuleActive) if (YukiHookAPI.Status.isXposedModuleActive)
context.snake(msg = "设置需要重启系统界面才能生效", actionText = "立即重启") { restartSystemUI(context) } context.snake(msg = "设置需要重启系统界面才能生效", actionText = "立即重启") { restartSystemUI(context) }
else context.snake(msg = "模块没有激活,更改不会生效") else context.snake(msg = "模块没有激活,更改不会生效")
/** 宿主广播接收器 */
private val moduleHandlerReceiver by lazy {
object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val isRegular = intent?.getBooleanExtra("isRegular", false) ?: false
val isValied = intent?.getBooleanExtra("isValied", false) ?: false
moduleHandlerCallback?.invoke(isRegular, isValied)
}
}
}
/** 通知广播接收器 */
private val remindHandlerReceiver by lazy {
object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val isGrasp = intent?.getBooleanExtra("isGrasp", false) ?: false
val isValied = intent?.getBooleanExtra("isValied", false) ?: false
remindHandlerCallback?.invoke(isGrasp, isValied)
}
}
}
} }

View File

@@ -0,0 +1,59 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* 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 2022/5/30.
*/
package com.fankes.coloros.notify.utils.tool
import android.content.Context
import com.fankes.coloros.notify.utils.factory.openBrowser
import com.fankes.coloros.notify.utils.factory.showDialog
import com.highcapable.yukihookapi.YukiHookAPI
import com.highcapable.yukihookapi.hook.factory.modulePrefs
import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData
/**
* [YukiHookAPI] 的自动推广工具类
*/
object YukiPromoteTool {
/** 推广已读存储键值 */
private val YUKI_PROMOTE_READED = PrefsData("yuki_promote_readed", false)
/**
* 显示推广对话框
* @param context 实例
*/
fun promote(context: Context) {
fun saveReaded() = context.modulePrefs.put(YUKI_PROMOTE_READED, value = true)
if (context.modulePrefs.get(YUKI_PROMOTE_READED).not())
context.showDialog {
title = "面向开发者的推广"
msg = "你想快速拥有一个自己的 Xposed 模块吗,你只需要拥有基础的 Android 开发经验以及使用 Kotlin 编程语言即可。\n\n" +
"快来体验 YukiHookAPI这是一个使用 Kotlin 重新构建的高效 Xposed Hook API助你的开发变得更轻松。"
confirmButton(text = "去看看") {
context.openBrowser(url = "https://github.com/fankes/YukiHookAPI")
saveReaded()
}
cancelButton(text = "我不是开发者") { saveReaded() }
noCancelable()
}
}
}

View File

@@ -421,6 +421,31 @@
android:textColor="@color/colorTextDark" android:textColor="@color/colorTextDark"
android:textSize="12sp" /> android:textSize="12sp" />
<com.fankes.coloros.notify.ui.view.MaterialSwitch
android:id="@+id/notify_media_panel_auto_exp_switch"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="5dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:text="启用媒体通知播放时自动展开"
android:textAllCaps="false"
android:textColor="@color/colorTextGray"
android:textSize="15sp" />
<TextView
android:id="@+id/notify_media_panel_auto_exp_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:alpha="0.6"
android:lineSpacingExtra="6dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:text="ColorOS 的媒体通知在播放的时候默认是折叠状态,开启后只要推送媒体通知以及恢复播放状态都会自动展开通知。"
android:textColor="@color/colorTextDark"
android:textSize="12sp" />
<com.fankes.coloros.notify.ui.view.MaterialSwitch <com.fankes.coloros.notify.ui.view.MaterialSwitch
android:id="@+id/notify_panel_config_switch" android:id="@+id/notify_panel_config_switch"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -440,8 +465,9 @@
android:layout_marginLeft="5dp" android:layout_marginLeft="5dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:layout_marginRight="5dp" android:layout_marginRight="5dp"
android:max="255" android:max="100"
android:min="0" /> android:min="0"
android:progress="75" />
<LinearLayout <LinearLayout
android:id="@+id/notify_panel_config_text_panel" android:id="@+id/notify_panel_config_text_panel"
@@ -461,7 +487,7 @@
android:gravity="center" android:gravity="center"
android:maxWidth="100dp" android:maxWidth="100dp"
android:singleLine="true" android:singleLine="true"
android:text="当前" android:text="当前"
android:textColor="@color/colorTextGray" android:textColor="@color/colorTextGray"
android:textSize="13.5sp" /> android:textSize="13.5sp" />
@@ -473,7 +499,7 @@
android:gravity="center" android:gravity="center"
android:maxWidth="100dp" android:maxWidth="100dp"
android:singleLine="true" android:singleLine="true"
android:text="%1" android:text="75%"
android:textColor="@color/colorTextGray" android:textColor="@color/colorTextGray"
android:textSize="15sp" android:textSize="15sp"
android:textStyle="bold" /> android:textStyle="bold" />
@@ -487,10 +513,16 @@
android:lineSpacingExtra="6dp" android:lineSpacingExtra="6dp"
android:paddingLeft="15dp" android:paddingLeft="15dp"
android:paddingRight="15dp" android:paddingRight="15dp"
android:text="开启自定义功能后你可以拖拽滑动条来调整通知面板的透明度0 为全透明,255 为不透明。" android:text="开启自定义功能后你可以拖拽滑动条来调整通知面板的透明度0% 为全透明,100% 为不透明。"
android:textColor="@color/colorTextDark" android:textColor="@color/colorTextDark"
android:textSize="12sp" /> android:textSize="12sp" />
<LinearLayout
android:id="@+id/notify_panel_config_warn_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -499,9 +531,24 @@
android:lineSpacingExtra="6dp" android:lineSpacingExtra="6dp"
android:paddingLeft="15dp" android:paddingLeft="15dp"
android:paddingRight="15dp" android:paddingRight="15dp"
android:text="此功能为实验性功能,后期不一定继续维护,且仅在 ColorOS 12.1 测试通过,不能保证可以在任何系统版本中生效,以及和各种通知栏主题模块配合使用,如有冲突请关闭此功能或禁用相关重复功能的主题模块。\n已知问题悬浮通知也会被透明在透明度较低的时候下拉会有阴影光晕后期看需求再解决。" android:text="此功能为实验性功能,后期不一定继续维护,且仅在 ColorOS 12.1 测试通过,不能保证可以在任何系统版本中生效,以及和各种通知栏主题模块配合使用,如有冲突请关闭此功能或禁用相关重复功能的主题模块。"
android:textColor="@color/colorTextDark" android:textColor="@color/colorTextDark"
android:textSize="12sp" /> android:textSize="12sp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:alpha="0.6"
android:lineSpacingExtra="6dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:text="已知问题:\n(1) 悬浮通知也会被透明,在透明度较低的时候下拉会有阴影光晕,松手释放后恢复正常,后期看需求再解决。\n(2) 媒体通知可能在低于 ColorOS 12.1 的系统上无法生效透明度,旧版本不再适配,该问题不会被修复。"
android:textColor="@color/colorTextDark"
android:textSize="12sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
@@ -516,15 +563,13 @@
android:elevation="0dp" android:elevation="0dp"
android:gravity="center" android:gravity="center"
android:orientation="vertical" android:orientation="vertical"
android:paddingLeft="10dp" android:paddingTop="15dp">
android:paddingTop="15dp"
android:paddingRight="10dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="5dp" android:layout_marginLeft="15dp"
android:layout_marginRight="5dp" android:layout_marginRight="15dp"
android:gravity="center|start"> android:gravity="center|start">
<ImageView <ImageView
@@ -547,8 +592,8 @@
android:id="@+id/notify_icon_fix_switch" android:id="@+id/notify_icon_fix_switch"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="5dp" android:layout_marginLeft="15dp"
android:layout_marginRight="5dp" android:layout_marginRight="15dp"
android:text="启用通知图标优化" android:text="启用通知图标优化"
android:textColor="@color/colorTextGray" android:textColor="@color/colorTextGray"
android:textSize="15sp" /> android:textSize="15sp" />
@@ -557,8 +602,8 @@
android:id="@+id/notify_icon_fix_button" android:id="@+id/notify_icon_fix_button"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="3dp" android:layout_marginLeft="13dp"
android:layout_marginRight="3dp" android:layout_marginRight="13dp"
android:layout_marginBottom="10dp" android:layout_marginBottom="10dp"
android:background="@drawable/bg_button_round" android:background="@drawable/bg_button_round"
android:gravity="center" android:gravity="center"
@@ -571,8 +616,8 @@
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="5dp" android:layout_marginLeft="15dp"
android:layout_marginRight="5dp" android:layout_marginRight="15dp"
android:layout_marginBottom="10dp" android:layout_marginBottom="10dp"
android:alpha="0.6" android:alpha="0.6"
android:lineSpacingExtra="6dp" android:lineSpacingExtra="6dp"
@@ -583,8 +628,8 @@
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="5dp" android:layout_marginLeft="15dp"
android:layout_marginRight="5dp" android:layout_marginRight="15dp"
android:layout_marginBottom="10dp" android:layout_marginBottom="10dp"
android:alpha="0.6" android:alpha="0.6"
android:lineSpacingExtra="6dp" android:lineSpacingExtra="6dp"
@@ -592,12 +637,119 @@
android:textColor="@color/colorTextDark" android:textColor="@color/colorTextDark"
android:textSize="12sp" /> android:textSize="12sp" />
<LinearLayout
android:id="@+id/notify_icon_custom_corner_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginBottom="5dp"
android:gravity="center|start"
android:text="调整通知栏中的图标边框圆角大小"
android:textAllCaps="false"
android:textColor="@color/colorTextGray"
android:textSize="15sp" />
<androidx.appcompat.widget.AppCompatSeekBar
android:id="@+id/notify_icon_custom_corner_seekbar"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="5dp"
android:max="10"
android:min="0"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:progress="10" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:gravity="center"
android:orientation="horizontal"
android:paddingTop="5dp"
android:paddingBottom="15dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:alpha="0.75"
android:ellipsize="end"
android:gravity="center"
android:maxWidth="100dp"
android:singleLine="true"
android:text="当前"
android:textColor="@color/colorTextGray"
android:textSize="13.5sp" />
<TextView
android:id="@+id/notify_icon_custom_corner_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="center"
android:maxWidth="100dp"
android:singleLine="true"
android:text="10 dp"
android:textColor="@color/colorTextGray"
android:textSize="15sp"
android:textStyle="bold" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:alpha="0.6"
android:lineSpacingExtra="6dp"
android:text="你可以拖拽滑动条来调整通知栏中图标的边框圆角大小,仅支持启用了 Android 12 通知栏风格的通知图标。"
android:textColor="@color/colorTextDark"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/notify_icon_force_app_icon_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:orientation="vertical">
<com.fankes.coloros.notify.ui.view.MaterialSwitch
android:id="@+id/notify_icon_force_app_icon_switch"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_marginBottom="5dp"
android:text="通知栏中的图标强制为 APP 图标"
android:textColor="@color/colorTextGray"
android:textSize="15sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:alpha="0.6"
android:lineSpacingExtra="6dp"
android:text="此选项默认关闭,开启后下拉通知栏中的通知图标将会被替换为 APP 自身图标,但是不会更改状态栏中的通知图标,这是一个破坏原生通知图标的行为,仅针对部分有需要的用户而添加,我们不推荐开启这个功能,请根据个人偏好进行选择是否需要开启。"
android:textColor="@color/colorTextDark"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/notify_icon_fix_notify_item" android:id="@+id/notify_icon_fix_notify_item"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="5dp" android:layout_marginLeft="15dp"
android:layout_marginRight="5dp" android:layout_marginRight="15dp"
android:orientation="vertical"> android:orientation="vertical">
<com.fankes.coloros.notify.ui.view.MaterialSwitch <com.fankes.coloros.notify.ui.view.MaterialSwitch
@@ -624,8 +776,8 @@
android:id="@+id/notify_icon_auto_sync_item" android:id="@+id/notify_icon_auto_sync_item"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="5dp" android:layout_marginLeft="15dp"
android:layout_marginRight="5dp" android:layout_marginRight="15dp"
android:animateLayoutChanges="true" android:animateLayoutChanges="true"
android:orientation="vertical"> android:orientation="vertical">

View File

@@ -1,12 +1,12 @@
plugins { plugins {
id 'com.android.application' version '7.1.3' apply false id 'com.android.application' version '7.2.0' apply false
id 'com.android.library' version '7.1.3' apply false id 'com.android.library' version '7.2.0' apply false
id 'org.jetbrains.kotlin.android' version '1.6.21' apply false id 'org.jetbrains.kotlin.android' version '1.6.21' apply false
} }
ext { ext {
appVersionName = "1.76" appVersionName = "1.85"
appVersionCode = 14 appVersionCode = 17
enableR8 = true enableR8 = true
} }

View File

@@ -1,6 +1,6 @@
#Sat Feb 26 13:04:39 CST 2022 #Wed May 25 04:24:55 CST 2022
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME