Compare commits
48 Commits
Author | SHA1 | Date | |
---|---|---|---|
fb44c4e945 | |||
a2fc95d765 | |||
0e3ef5418c | |||
4e5e2cee09 | |||
7b4b728523 | |||
9b6540df65 | |||
3e8982aad0 | |||
085f2498c8 | |||
a1e01d1d33 | |||
03aa550487 | |||
ea632b8892 | |||
|
69847a0b0b | ||
|
4cdbfa944d | ||
|
9edb04cf08 | ||
|
071c98e8f3 | ||
|
a317cc07f5 | ||
ef0392a168 | |||
32e9ee3c8b | |||
296f12d07a | |||
df99256231 | |||
60128bcb1a | |||
54aec1051f | |||
121170ba65 | |||
a2d282c3f1 | |||
4d0098f1b8 | |||
49f6bc921c | |||
f94286351b | |||
faad964359 | |||
78308ac558 | |||
03fd389e13 | |||
fb067577af | |||
da5d4eba1b | |||
|
aa22ee05c6 | ||
08873b3e1f | |||
7bfd2046ca | |||
f57e658900 | |||
|
b7ec4559cf | ||
c707f8a3f7 | |||
|
350823f4ec | ||
|
26c6241d38 | ||
|
6e0c42638f | ||
|
8c6d7d7258 | ||
8b9ecc1d87 | |||
df1df6aabf | |||
e618efe29e | |||
9468c0b696 | |||
9bf843eef4 | |||
a0f40012c6 |
28
.github/ISSUE_TEMPLATE/----------.md
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
name: 通知优化图标适配反馈
|
||||
about: 提交通知图标优化适配必须使用此模板提交
|
||||
title: "[通知优化图标适配反馈]"
|
||||
labels: To be adapted
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**需要适配的 APP 名称/包名/通知图标颜色 (必填)**
|
||||
|
||||
* (示例:小米音乐/com.miui.player/#fff16033)
|
||||
|
||||
*
|
||||
|
||||
**提供相关 APP 的下载渠道截图以及简要说明用途 (必填)**
|
||||
|
||||
*
|
||||
|
||||
**提供相关 APP 的通知单色图标适配素材 大小 50x50 (选填)**
|
||||
|
||||
* (可填写资源下载地址或直接添加附件提交,不接受百度网盘、天翼云盘以及各种快传、私有云盘)
|
||||
|
||||
* (若直接在附件提交这里可不填)
|
||||
|
||||
<!--- 提交时请将示例内容全部删除 --->
|
||||
<!--- 不按规定提交的 issues 将直接被关闭 --->
|
||||
<!--- Create by Template --->
|
51
.github/ISSUE_TEMPLATE/----bug---.md
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
---
|
||||
name: 问题与 BUG 反馈
|
||||
about: 问题反馈必须使用此模板进行提交
|
||||
title: "[问题与 BUG 反馈] *简要描述问题原因*"
|
||||
labels: bug
|
||||
assignees: fankes
|
||||
|
||||
---
|
||||
|
||||
**MIUI 版本(必填)**
|
||||
|
||||
*
|
||||
|
||||
**MIUI 版本类型(请保留一个)**
|
||||
|
||||
* 公测版/内测版/稳定版
|
||||
|
||||
**Android 版本(必填)**
|
||||
|
||||
*
|
||||
|
||||
**模块版本(必填)**
|
||||
|
||||
*
|
||||
|
||||
**使用的 Xposed 框架名称与框架版本(必填)**
|
||||
|
||||
*
|
||||
|
||||
**同时使用的带有系统界面作用域的 Xposed 模块(选填)**
|
||||
|
||||
* (没有可空)
|
||||
|
||||
**问题的具体描述**
|
||||
|
||||
* (复现步骤、前提以及详细截图和录屏演示)
|
||||
|
||||
|
||||
**提供模块问题 Log 或必要 Log**
|
||||
|
||||
* (LSPosed 可在日志管理中查看并筛选包含 `MIUINativeNotifyIcon` 的日志)
|
||||
|
||||
<details><summary>展开查看</summary><pre><code>
|
||||
|
||||
(此处粘贴问题Log)
|
||||
|
||||
</code></pre></details>
|
||||
|
||||
<!--- 提交时请将示例内容全部删除 --->
|
||||
<!--- 不按规定提交的 issues 将直接被关闭 --->
|
||||
<!--- Create by Template --->
|
@@ -26,10 +26,12 @@ IconDataBean(
|
||||
appName = "", // APP 名称
|
||||
packageName = "", // APP 包名
|
||||
iconBitmap = ("").bitmap, // 位图数据 Base64
|
||||
iconColor = 0, // 通知栏中显示的图标颜色 - 设置为 0 使用系统默认颜色 (不设置颜色可不写)
|
||||
contributorName = "" // 贡献者昵称
|
||||
)
|
||||
```
|
||||
|
||||
- 图标大小建议保持在 50x50
|
||||
- 提交时请将后方的注释删除,否则不予合并代码
|
||||
|
||||
## 其它要求
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
<br/><br/>
|
||||
<img src="https://github.com/fankes/MIUINativeNotifyIcon/blob/master/app/src/main/ic_launcher-playstore.png" width = "100" height = "100"/>
|
||||
<br/>
|
||||
@@ -12,7 +12,7 @@ Fix the native notification bar icon function abandoned by the MIUI development
|
||||
# 开始使用
|
||||
|
||||
点击下载最新版本
|
||||
<a href='https://github.com/fankes/MIUINativeNotifyIcon/releases'></a>
|
||||
<a href='https://github.com/fankes/MIUINativeNotifyIcon/releases'></a>
|
||||
<br/><br/>
|
||||
⚠️ 适配说明<br/>
|
||||
|
||||
|
@@ -64,8 +64,8 @@ dependencies {
|
||||
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
|
||||
compileOnly 'de.robv.android.xposed:api:82'
|
||||
implementation 'com.highcapable.yukihookapi:api:1.0.1'
|
||||
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.1'
|
||||
implementation 'com.highcapable.yukihookapi:api:1.0.2'
|
||||
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.2'
|
||||
implementation 'com.geyifeng.immersionbar:immersionbar:3.2.0'
|
||||
implementation 'com.geyifeng.immersionbar:immersionbar-ktx:3.2.0'
|
||||
implementation 'androidx.core:core-ktx:1.7.0'
|
||||
|
@@ -53,5 +53,4 @@
|
||||
android:exported="false"
|
||||
android:screenOrientation="behind" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
@@ -31,6 +31,7 @@ import java.io.Serializable
|
||||
* @param appName APP 名称 - 仅限默认语言区域
|
||||
* @param packageName 包名
|
||||
* @param iconBitmap 图标位图
|
||||
* @param iconColor 通知栏中显示的图标颜色 - 设置为 0 使用系统默认颜色
|
||||
* @param contributorName 贡献者昵称
|
||||
* @param isEnabled 是否默认启用替换彩色图标 - 关闭后将全部停止替换
|
||||
* @param isEnabledAll 是否默认启用替换全部图标
|
||||
@@ -39,6 +40,7 @@ data class IconDataBean(
|
||||
var appName: String,
|
||||
var packageName: String,
|
||||
var iconBitmap: Bitmap,
|
||||
var iconColor: Int = 0,
|
||||
var contributorName: String,
|
||||
var isEnabled: Boolean,
|
||||
var isEnabledAll: Boolean,
|
||||
|
@@ -1,24 +0,0 @@
|
||||
package com.fankes.miui.notify.data
|
||||
|
||||
import com.fankes.miui.notify.data.model.LoggedInUser
|
||||
import java.io.IOException
|
||||
|
||||
/**
|
||||
* Class that handles authentication w/ login credentials and retrieves user information.
|
||||
*/
|
||||
class LoginDataSource {
|
||||
|
||||
fun login(username: String, password: String): Result<LoggedInUser> {
|
||||
try {
|
||||
// TODO: handle loggedInUser authentication
|
||||
val fakeUser = LoggedInUser(java.util.UUID.randomUUID().toString(), "Jane Doe")
|
||||
return Result.Success(fakeUser)
|
||||
} catch (e: Throwable) {
|
||||
return Result.Error(IOException("Error logging in", e))
|
||||
}
|
||||
}
|
||||
|
||||
fun logout() {
|
||||
// TODO: revoke authentication
|
||||
}
|
||||
}
|
@@ -1,46 +0,0 @@
|
||||
package com.fankes.miui.notify.data
|
||||
|
||||
import com.fankes.miui.notify.data.model.LoggedInUser
|
||||
|
||||
/**
|
||||
* Class that requests authentication and user information from the remote data source and
|
||||
* maintains an in-memory cache of login status and user credentials information.
|
||||
*/
|
||||
|
||||
class LoginRepository(val dataSource: LoginDataSource) {
|
||||
|
||||
// in-memory cache of the loggedInUser object
|
||||
var user: LoggedInUser? = null
|
||||
private set
|
||||
|
||||
val isLoggedIn: Boolean
|
||||
get() = user != null
|
||||
|
||||
init {
|
||||
// If user credentials will be cached in local storage, it is recommended it be encrypted
|
||||
// @see https://developer.android.com/training/articles/keystore
|
||||
user = null
|
||||
}
|
||||
|
||||
fun logout() {
|
||||
user = null
|
||||
dataSource.logout()
|
||||
}
|
||||
|
||||
fun login(username: String, password: String): Result<LoggedInUser> {
|
||||
// handle login
|
||||
val result = dataSource.login(username, password)
|
||||
|
||||
if (result is Result.Success) {
|
||||
setLoggedInUser(result.data)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun setLoggedInUser(loggedInUser: LoggedInUser) {
|
||||
this.user = loggedInUser
|
||||
// If user credentials will be cached in local storage, it is recommended it be encrypted
|
||||
// @see https://developer.android.com/training/articles/keystore
|
||||
}
|
||||
}
|
@@ -1,18 +0,0 @@
|
||||
package com.fankes.miui.notify.data
|
||||
|
||||
/**
|
||||
* A generic class that holds a value with its loading status.
|
||||
* @param <T>
|
||||
*/
|
||||
sealed class Result<out T : Any> {
|
||||
|
||||
data class Success<out T : Any>(val data: T) : Result<T>()
|
||||
data class Error(val exception: Exception) : Result<Nothing>()
|
||||
|
||||
override fun toString(): String {
|
||||
return when (this) {
|
||||
is Success<*> -> "Success[data=$data]"
|
||||
is Error -> "Error[exception=$exception]"
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
package com.fankes.miui.notify.data.model
|
||||
|
||||
/**
|
||||
* Data class that captures user information for logged in users retrieved from LoginRepository
|
||||
*/
|
||||
data class LoggedInUser(
|
||||
val userId: String,
|
||||
val displayName: String
|
||||
)
|
@@ -30,7 +30,7 @@ object HookConst {
|
||||
const val ENABLE_MODULE_LOG = "_enable_module_log"
|
||||
const val ENABLE_HIDE_ICON = "_hide_icon"
|
||||
const val ENABLE_COLOR_ICON_HOOK = "_color_icon_hook"
|
||||
const val ENABLE_NOTIFY_ICON_HOOK = "_notify_icon_hook"
|
||||
const val ENABLE_NOTIFY_ICON_FIX = "_notify_icon_fix"
|
||||
|
||||
const val SYSTEMUI_PACKAGE_NAME = "com.android.systemui"
|
||||
}
|
@@ -28,6 +28,7 @@ import android.graphics.Color
|
||||
import android.graphics.Outline
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.Icon
|
||||
import android.os.Build
|
||||
import android.service.notification.StatusBarNotification
|
||||
import android.view.View
|
||||
import android.view.ViewOutlineProvider
|
||||
@@ -36,15 +37,17 @@ import androidx.core.graphics.drawable.toBitmap
|
||||
import com.fankes.miui.notify.hook.HookConst.ENABLE_COLOR_ICON_HOOK
|
||||
import com.fankes.miui.notify.hook.HookConst.ENABLE_MODULE
|
||||
import com.fankes.miui.notify.hook.HookConst.ENABLE_MODULE_LOG
|
||||
import com.fankes.miui.notify.hook.HookConst.ENABLE_NOTIFY_ICON_HOOK
|
||||
import com.fankes.miui.notify.hook.HookConst.ENABLE_NOTIFY_ICON_FIX
|
||||
import com.fankes.miui.notify.hook.HookConst.SYSTEMUI_PACKAGE_NAME
|
||||
import com.fankes.miui.notify.hook.factory.isAppNotifyHookAllOf
|
||||
import com.fankes.miui.notify.hook.factory.isAppNotifyHookOf
|
||||
import com.fankes.miui.notify.params.IconPackParams
|
||||
import com.fankes.miui.notify.utils.*
|
||||
import com.fankes.miui.notify.utils.drawable.drawabletoolbox.DrawableBuilder
|
||||
import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed
|
||||
import com.highcapable.yukihookapi.hook.bean.VariousClass
|
||||
import com.highcapable.yukihookapi.hook.factory.*
|
||||
import com.highcapable.yukihookapi.hook.log.loggerD
|
||||
import com.highcapable.yukihookapi.hook.log.loggerW
|
||||
import com.highcapable.yukihookapi.hook.param.PackageParam
|
||||
import com.highcapable.yukihookapi.hook.type.android.ContextClass
|
||||
@@ -73,9 +76,6 @@ class HookEntry : YukiHookXposedInitProxy {
|
||||
private const val NotificationViewWrapperClass =
|
||||
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationViewWrapper"
|
||||
|
||||
/** 原生存在的类 */
|
||||
private const val StatusBarIconViewClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.StatusBarIconView"
|
||||
|
||||
/** 原生存在的类 */
|
||||
private const val ContrastColorUtilClass = "com.android.internal.util.ContrastColorUtil"
|
||||
|
||||
@@ -105,8 +105,13 @@ class HookEntry : YukiHookXposedInitProxy {
|
||||
*/
|
||||
private fun PackageParam.isGrayscaleIcon(context: Context, drawable: Drawable) = safeOfFalse {
|
||||
ContrastColorUtilClass.clazz.let {
|
||||
it.method(name = "isGrayscaleIcon", DrawableClass)
|
||||
?.call<Boolean>(it.method(name = "getInstance", ContextClass)?.callStatic(context), drawable) ?: false
|
||||
it.method {
|
||||
name = "isGrayscaleIcon"
|
||||
param(DrawableClass)
|
||||
}.get(it.method {
|
||||
name = "getInstance"
|
||||
param(ContextClass)
|
||||
}.get().invoke(context)).invoke<Boolean>(drawable) ?: false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +120,7 @@ class HookEntry : YukiHookXposedInitProxy {
|
||||
* @return [Boolean]
|
||||
*/
|
||||
private fun PackageParam.isShowMiuiStyle() = safeOfFalse {
|
||||
NotificationUtilClass.clazz.method(name = "showMiuiStyle")?.callStatic() ?: false
|
||||
NotificationUtilClass.clazz.method { name = "showMiuiStyle" }.get().invoke() ?: false
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,14 +139,59 @@ class HookEntry : YukiHookXposedInitProxy {
|
||||
* @return [String]
|
||||
*/
|
||||
private fun PackageParam.findAppName(instance: Any?) = safeOf(default = "<unknown>") {
|
||||
ExpandedNotificationClass.clazz.method(name = "getAppName")?.call(instance) ?: "<empty>"
|
||||
ExpandedNotificationClass.clazz.method { name = "getAppName" }.get(instance).invoke() ?: "<empty>"
|
||||
}
|
||||
|
||||
/**
|
||||
* 适配通知栏、状态栏图标
|
||||
*
|
||||
* 适配第三方图标包对系统包管理器更换图标后的彩色图标
|
||||
*
|
||||
* 自动识别 MIPUSH 图标
|
||||
* @param context 实例
|
||||
* @param iconDrawable 原始图标
|
||||
* @return [Drawable] 适配的图标
|
||||
*/
|
||||
private fun StatusBarNotification.compatNotifyIcon(context: Context, iconDrawable: Drawable) = safeOf(iconDrawable) {
|
||||
/** 给 MIPUSH 设置 APP 自己的图标 */
|
||||
if (isXmsf && opPkgName.isNotBlank())
|
||||
context.packageManager.getPackageInfo(opPkgName, 0).applicationInfo.loadIcon(context.packageManager)
|
||||
else iconDrawable
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取推送通知的包名
|
||||
*
|
||||
* 自动兼容旧版本系统
|
||||
* @return [String]
|
||||
*/
|
||||
private val StatusBarNotification.compatOpPkgName
|
||||
get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) opPkg else packageName ?: ""
|
||||
|
||||
/**
|
||||
* 判断通知是否来自 MIPUSH
|
||||
* @return [Boolean]
|
||||
*/
|
||||
private val StatusBarNotification.isXmsf get() = opPkgName == "com.xiaomi.xmsf"
|
||||
private val StatusBarNotification.isXmsf get() = compatOpPkgName == "com.xiaomi.xmsf"
|
||||
|
||||
/**
|
||||
* 获取推送通知的包名
|
||||
*
|
||||
* 自动判断 MIPUSH
|
||||
* @return [String]
|
||||
*/
|
||||
private val StatusBarNotification.opPkgName get() = if (isXmsf) xmsfPkgName else compatOpPkgName
|
||||
|
||||
/**
|
||||
* 获取 MIPUSH 通知真实包名
|
||||
* @return [String]
|
||||
*/
|
||||
private val StatusBarNotification.xmsfPkgName: String
|
||||
get() {
|
||||
val xmsfPkg = notification.extras.getString("xmsf_target_package") ?: ""
|
||||
val targetPkg = notification.extras.getString("target_package") ?: ""
|
||||
return xmsfPkg.ifBlank { targetPkg.ifBlank { compatOpPkgName } }
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全局上下文
|
||||
@@ -149,7 +199,9 @@ class HookEntry : YukiHookXposedInitProxy {
|
||||
*/
|
||||
private val PackageParam.globalContext
|
||||
get() = safeOfNull {
|
||||
SystemUIApplicationClass.clazz.method(name = "getContext")?.callStatic<Context>()
|
||||
if (SystemUIApplicationClass.clazz.hasMethod(name = "getContext"))
|
||||
SystemUIApplicationClass.clazz.method { name = "getContext" }.get().invoke<Context>()
|
||||
else null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -168,13 +220,15 @@ class HookEntry : YukiHookXposedInitProxy {
|
||||
it: (Bitmap) -> Unit
|
||||
) = safeRun(msg = "GetSmallIconOnSet") {
|
||||
if (iconDrawable == null) return@safeRun
|
||||
/** 如果没开启修复 APP 的彩色图标 */
|
||||
if (!prefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)) return@safeRun
|
||||
/** 判断是否不是灰度图标 */
|
||||
val isNotGrayscaleIcon = !isGrayscaleIcon(context, iconDrawable)
|
||||
/** 获取通知对象 - 由于 MIUI 的版本迭代不规范性可能是空的 */
|
||||
expandedNf?.also { notifyInstance ->
|
||||
/** 目标彩色通知 APP 图标 */
|
||||
var customIcon: Bitmap? = null
|
||||
if (prefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true))
|
||||
if (prefs.getBoolean(ENABLE_NOTIFY_ICON_FIX, default = true))
|
||||
run {
|
||||
IconPackParams.iconDatas.forEach {
|
||||
if ((notifyInstance.opPkgName == it.packageName ||
|
||||
@@ -187,11 +241,14 @@ class HookEntry : YukiHookXposedInitProxy {
|
||||
}
|
||||
}
|
||||
}
|
||||
/** 打印日志 */
|
||||
if (prefs.getBoolean(ENABLE_MODULE_LOG))
|
||||
loggerD(msg = "hook Icon [${findAppName(notifyInstance)}][${notifyInstance.opPkgName}] custom [${customIcon != null}] grayscale [${!isNotGrayscaleIcon}]")
|
||||
when {
|
||||
/** 如果开启了修复 APP 的彩色图标 */
|
||||
customIcon != null && prefs.getBoolean(ENABLE_NOTIFY_ICON_HOOK, default = true) -> it(customIcon!!)
|
||||
/** 处理自定义通知图标优化 */
|
||||
customIcon != null -> it(customIcon!!)
|
||||
/** 若不是灰度图标自动处理为圆角 */
|
||||
isNotGrayscaleIcon -> it(iconDrawable.toBitmap().round(15.dp(context)))
|
||||
isNotGrayscaleIcon -> it(expandedNf.compatNotifyIcon(context, iconDrawable).toBitmap().round(15.dp(context)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,10 +263,12 @@ class HookEntry : YukiHookXposedInitProxy {
|
||||
*/
|
||||
private fun PackageParam.hookNotifyIconOnSet(context: Context, expandedNf: StatusBarNotification?, iconImageView: ImageView) =
|
||||
safeRun(msg = "AutoSetAppIconOnSet") {
|
||||
/** 如果没开启修复 APP 的彩色图标 */
|
||||
if (!prefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)) return@safeRun
|
||||
/** 获取通知对象 - 由于 MIUI 的版本迭代不规范性可能是空的 */
|
||||
expandedNf?.let { notifyInstance ->
|
||||
/** 是否 Hook 彩色通知图标 */
|
||||
val isHookColorIcon = prefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)
|
||||
/** 是否开启修复 APP 的彩色图标 */
|
||||
val isNotifyIconFix = prefs.getBoolean(ENABLE_NOTIFY_ICON_FIX, default = true)
|
||||
|
||||
/** 新版风格反色 */
|
||||
val newStyle = if (context.isSystemInDarkMode) 0xFF2D2D2D.toInt() else Color.WHITE
|
||||
@@ -217,6 +276,21 @@ class HookEntry : YukiHookXposedInitProxy {
|
||||
/** 旧版风格反色 */
|
||||
val oldStyle = if (context.isNotSystemInDarkMode) 0xFF707070.toInt() else Color.WHITE
|
||||
|
||||
/** 通知图标原始颜色 */
|
||||
val iconColor = notifyInstance.notification.color
|
||||
|
||||
/** 是否有通知栏图标颜色 */
|
||||
val hasIconColor = iconColor != 0
|
||||
|
||||
/** 通知图标适配颜色 */
|
||||
val supportColor = iconColor.let {
|
||||
when {
|
||||
isUpperOfAndroidS -> newStyle
|
||||
it == 0 -> oldStyle
|
||||
else -> it
|
||||
}
|
||||
}
|
||||
|
||||
/** 获取通知小图标 */
|
||||
val iconDrawable = notifyInstance.notification.smallIcon.loadDrawable(context)
|
||||
|
||||
@@ -225,53 +299,64 @@ class HookEntry : YukiHookXposedInitProxy {
|
||||
|
||||
/** 自定义默认小图标 */
|
||||
var customIcon: Bitmap? = null
|
||||
if (isHookColorIcon) run {
|
||||
|
||||
/** 自定义默认小图标颜色 */
|
||||
var customIconColor = 0
|
||||
|
||||
if (isNotifyIconFix) run {
|
||||
IconPackParams.iconDatas.forEach {
|
||||
if ((notifyInstance.opPkgName == it.packageName ||
|
||||
findAppName(notifyInstance) == it.appName) &&
|
||||
isAppNotifyHookOf(it)
|
||||
) {
|
||||
if (!isGrayscaleIcon || isAppNotifyHookAllOf(it))
|
||||
if (!isGrayscaleIcon || isAppNotifyHookAllOf(it)) {
|
||||
customIcon = it.iconBitmap
|
||||
return@run
|
||||
customIconColor = it.iconColor
|
||||
return@run
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** 如果开启了修复 APP 的彩色图标 */
|
||||
if (customIcon != null && prefs.getBoolean(ENABLE_NOTIFY_ICON_HOOK, default = true))
|
||||
/** 处理自定义通知图标优化 */
|
||||
if (customIcon != null)
|
||||
iconImageView.apply {
|
||||
/** 设置自定义小图标 */
|
||||
setImageBitmap(customIcon)
|
||||
/** 上色 */
|
||||
setColorFilter(if (isUpperOfAndroidS) newStyle else oldStyle)
|
||||
setColorFilter(if (isUpperOfAndroidS || customIconColor == 0) supportColor else customIconColor)
|
||||
/** Android 12 设置图标外圈颜色 */
|
||||
if (isUpperOfAndroidS && customIconColor != 0)
|
||||
background = DrawableBuilder().rounded().solidColor(customIconColor).build()
|
||||
}
|
||||
else {
|
||||
/** 重新设置图标 - 防止系统更改它 */
|
||||
iconImageView.setImageDrawable(iconDrawable)
|
||||
/** 判断是否开启 Hook 彩色图标 */
|
||||
if (isHookColorIcon) {
|
||||
/** 判断如果是灰度图标就给他设置一个白色颜色遮罩 */
|
||||
if (isGrayscaleIcon)
|
||||
iconImageView.setColorFilter(if (isUpperOfAndroidS) newStyle else oldStyle)
|
||||
else
|
||||
iconImageView.apply {
|
||||
clipToOutline = true
|
||||
/** 设置一个圆角轮廓裁切 */
|
||||
outlineProvider = object : ViewOutlineProvider() {
|
||||
override fun getOutline(view: View, out: Outline) {
|
||||
out.setRoundRect(
|
||||
0, 0,
|
||||
view.width, view.height, 5.dp(context)
|
||||
)
|
||||
}
|
||||
}
|
||||
/** 清除原生的背景边距设置 */
|
||||
if (isUpperOfAndroidS) setPadding(0, 0, 0, 0)
|
||||
/** 清除原生的主题色背景圆圈颜色 */
|
||||
if (isUpperOfAndroidS) background = null
|
||||
/** 判断如果是灰度图标就给他设置一个白色颜色遮罩 */
|
||||
if (isGrayscaleIcon) iconImageView.apply {
|
||||
/** 设置图标着色 */
|
||||
setColorFilter(supportColor)
|
||||
/** Android 12 设置图标外圈颜色 */
|
||||
if (isUpperOfAndroidS && hasIconColor)
|
||||
background = DrawableBuilder().rounded().solidColor(iconColor).build()
|
||||
} else iconImageView.apply {
|
||||
/** 重新设置图标 */
|
||||
setImageDrawable(expandedNf.compatNotifyIcon(context, iconDrawable))
|
||||
/** 设置裁切到边界 */
|
||||
clipToOutline = true
|
||||
/** 设置一个圆角轮廓裁切 */
|
||||
outlineProvider = object : ViewOutlineProvider() {
|
||||
override fun getOutline(view: View, out: Outline) {
|
||||
out.setRoundRect(
|
||||
0, 0,
|
||||
view.width, view.height, 5.dp(context)
|
||||
)
|
||||
}
|
||||
/** 否则一律设置灰度图标 */
|
||||
} else iconImageView.setColorFilter(if (isUpperOfAndroidS) newStyle else oldStyle)
|
||||
}
|
||||
/** 清除原生的背景边距设置 */
|
||||
if (isUpperOfAndroidS) setPadding(0, 0, 0, 0)
|
||||
/** 清除原生的主题色背景圆圈颜色 */
|
||||
if (isUpperOfAndroidS) background = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -296,33 +381,32 @@ class HookEntry : YukiHookXposedInitProxy {
|
||||
val isNotGrayscaleIcon = !isGrayscaleIcon(context, iconDrawable)
|
||||
|
||||
/** 获取目标修复彩色图标的 APP */
|
||||
var isTargetApp = false
|
||||
run {
|
||||
IconPackParams.iconDatas.forEach {
|
||||
if ((notifyInstance.opPkgName == it.packageName ||
|
||||
findAppName(notifyInstance) == it.appName) &&
|
||||
isAppNotifyHookOf(it)
|
||||
) {
|
||||
if (isNotGrayscaleIcon || isAppNotifyHookAllOf(it)) isTargetApp = true
|
||||
return@run
|
||||
var isTargetFixApp = false
|
||||
/** 如果开启了自定义通知图标优化 */
|
||||
if (prefs.getBoolean(ENABLE_NOTIFY_ICON_FIX, default = true))
|
||||
run {
|
||||
IconPackParams.iconDatas.forEach {
|
||||
if ((notifyInstance.opPkgName == it.packageName ||
|
||||
findAppName(notifyInstance) == it.appName) &&
|
||||
isAppNotifyHookOf(it)
|
||||
) {
|
||||
if (isNotGrayscaleIcon || isAppNotifyHookAllOf(it)) isTargetFixApp = true
|
||||
return@run
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 如果开启了修复 APP 的彩色图标
|
||||
* 只要不是灰度就返回彩色图标
|
||||
* 否则不对颜色进行反色处理防止一些系统图标出现异常
|
||||
*/
|
||||
if (isTargetApp && prefs.getBoolean(ENABLE_NOTIFY_ICON_HOOK, default = true))
|
||||
false
|
||||
else isNotGrayscaleIcon
|
||||
if (isTargetFixApp) false else isNotGrayscaleIcon
|
||||
} ?: true
|
||||
} else false
|
||||
|
||||
override fun onHook() = encase {
|
||||
configs {
|
||||
debugTag = "MIUINativeNotifyIcon"
|
||||
isDebug = prefs.getBoolean(ENABLE_MODULE_LOG)
|
||||
isDebug = false
|
||||
}
|
||||
loadApp(SYSTEMUI_PACKAGE_NAME) {
|
||||
when {
|
||||
@@ -391,33 +475,8 @@ class HookEntry : YukiHookXposedInitProxy {
|
||||
}
|
||||
}
|
||||
}
|
||||
findClass(StatusBarIconViewClass).hook {
|
||||
/** 修复通知图标为彩色 - MIPUSH 修复 */
|
||||
injectMember {
|
||||
method { name = "updateIconColor" }
|
||||
afterHook {
|
||||
/** 获取自身 */
|
||||
val iconImageView = instance<ImageView?>() ?: return@afterHook
|
||||
|
||||
/** 获取通知实例 */
|
||||
val expandedNf = field { name = "mNotification" }.of<StatusBarNotification>(instance)
|
||||
|
||||
/**
|
||||
* 强制设置图标 - 防止 MIPUSH 不生效
|
||||
* 由于之前版本没有 [hasIgnoreStatusBarIconColor] 判断 - MIPUSH 的图标颜色也是白色的
|
||||
* 所以之前的版本取消这个 Hook - 实在找不到设置图标的地方 - 状态栏图标就彩色吧
|
||||
*/
|
||||
if (hasIgnoreStatusBarIconColor() && expandedNf?.isXmsf == true)
|
||||
hookSmallIconOnSet(
|
||||
context = iconImageView.context,
|
||||
expandedNf,
|
||||
expandedNf.notification?.smallIcon?.loadDrawable(iconImageView.context)
|
||||
) { icon -> iconImageView.setImageBitmap(icon) }
|
||||
}
|
||||
}
|
||||
}
|
||||
if (NotificationHeaderViewWrapperInjectorClass.hasClass)
|
||||
findClass(NotificationHeaderViewWrapperInjectorClass).hook {
|
||||
NotificationHeaderViewWrapperInjectorClass.hook {
|
||||
/** 修复下拉通知图标自动设置回 APP 图标的方法 */
|
||||
injectMember {
|
||||
var isUseLegacy = false
|
||||
@@ -457,30 +516,30 @@ class HookEntry : YukiHookXposedInitProxy {
|
||||
}
|
||||
}
|
||||
else
|
||||
findClass(NotificationHeaderViewWrapperClass).hook {
|
||||
NotificationHeaderViewWrapperClass.hook {
|
||||
/** 之前的版本解决方案 */
|
||||
injectMember {
|
||||
method { name = "handleHeaderViews" }
|
||||
afterHook {
|
||||
/** 对于之前没有通知图标色彩判断功能的版本判断是 MIUI 样式就停止 Hook */
|
||||
if (!hasIgnoreStatusBarIconColor() && isShowMiuiStyle()) return@afterHook
|
||||
|
||||
/** 获取小图标 */
|
||||
val iconImageView = field {
|
||||
classSet = NotificationHeaderViewWrapperClass.clazz
|
||||
name = "mIcon"
|
||||
}.of<ImageView>(instance) ?: return@afterHook
|
||||
/** 从父类中得到 mRow 变量 - [ExpandableNotificationRowClass] */
|
||||
field {
|
||||
classSet = NotificationViewWrapperClass.clazz
|
||||
name = "mRow"
|
||||
}.get(instance).apply {
|
||||
/** 获取其中的得到通知方法 */
|
||||
val expandedNf =
|
||||
ExpandableNotificationRowClass.clazz.method(name = "getStatusBarNotification")
|
||||
?.call<StatusBarNotification>(instance = self)
|
||||
/** 执行 Hook */
|
||||
hookNotifyIconOnSet(iconImageView.context, expandedNf, iconImageView)
|
||||
}
|
||||
val iconImageView =
|
||||
NotificationHeaderViewWrapperClass.clazz
|
||||
.field { name = "mIcon" }.of<ImageView>(instance) ?: return@afterHook
|
||||
|
||||
/**
|
||||
* 从父类中得到 mRow 变量 - [ExpandableNotificationRowClass]
|
||||
* 获取其中的得到通知方法
|
||||
*/
|
||||
val expandedNf =
|
||||
ExpandableNotificationRowClass.clazz
|
||||
.method { name = "getStatusBarNotification" }
|
||||
.get(NotificationViewWrapperClass.clazz.field { name = "mRow" }.get(instance).self)
|
||||
.invoke<StatusBarNotification>()
|
||||
/** 执行 Hook */
|
||||
hookNotifyIconOnSet(iconImageView.context, expandedNf, iconImageView)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -20,7 +20,7 @@
|
||||
*
|
||||
* This file is Created by fankes on 2022/1/30.
|
||||
*/
|
||||
@file:Suppress("SetTextI18n", "InflateParams")
|
||||
@file:Suppress("SetTextI18n", "InflateParams", "DEPRECATION")
|
||||
|
||||
package com.fankes.miui.notify.ui
|
||||
|
||||
@@ -33,7 +33,6 @@ import android.view.ViewGroup
|
||||
import android.widget.BaseAdapter
|
||||
import android.widget.ListView
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
import androidx.core.view.isVisible
|
||||
import com.fankes.miui.notify.R
|
||||
@@ -45,6 +44,8 @@ import com.fankes.miui.notify.params.IconPackParams
|
||||
import com.fankes.miui.notify.ui.base.BaseActivity
|
||||
import com.fankes.miui.notify.utils.SystemUITool
|
||||
import com.fankes.miui.notify.utils.showDialog
|
||||
import com.fankes.miui.notify.utils.snake
|
||||
import com.fankes.miui.notify.utils.toast
|
||||
import com.fankes.miui.notify.view.MaterialSwitch
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
|
||||
@@ -56,6 +57,9 @@ class ConfigureActivity : BaseActivity() {
|
||||
/** 回调适配器改变 */
|
||||
private var onChanged: (() -> Unit)? = null
|
||||
|
||||
/** 回调滚动事件改变 */
|
||||
private var onScrollEvent: ((Boolean) -> Unit)? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_config)
|
||||
@@ -63,6 +67,15 @@ class ConfigureActivity : BaseActivity() {
|
||||
findViewById<View>(R.id.title_back_icon).setOnClickListener { onBackPressed() }
|
||||
/** 刷新适配器结果相关 */
|
||||
refreshAdapterResult()
|
||||
/** 设置上下按钮点击事件 */
|
||||
findViewById<View>(R.id.config_title_up).setOnClickListener {
|
||||
snake(msg = "滚动到顶部")
|
||||
onScrollEvent?.invoke(false)
|
||||
}
|
||||
findViewById<View>(R.id.config_title_down).setOnClickListener {
|
||||
snake(msg = "滚动到底部")
|
||||
onScrollEvent?.invoke(true)
|
||||
}
|
||||
/** 设置过滤按钮点击事件 */
|
||||
findViewById<View>(R.id.config_title_filter).setOnClickListener {
|
||||
showDialog {
|
||||
@@ -84,7 +97,7 @@ class ConfigureActivity : BaseActivity() {
|
||||
onChanged?.invoke()
|
||||
refreshAdapterResult()
|
||||
} else {
|
||||
Toast.makeText(applicationContext, "条件不能为空", Toast.LENGTH_SHORT).show()
|
||||
toast(msg = "条件不能为空")
|
||||
it.performClick()
|
||||
}
|
||||
}
|
||||
@@ -126,6 +139,10 @@ class ConfigureActivity : BaseActivity() {
|
||||
} else holder = convertView.tag as ViewHolder
|
||||
getItem(position).also {
|
||||
holder.appIcon.setImageBitmap(it.iconBitmap)
|
||||
(if (it.iconColor != 0) it.iconColor else resources.getColor(R.color.colorTextGray)).also { color ->
|
||||
holder.appIcon.setColorFilter(color)
|
||||
holder.appName.setTextColor(color)
|
||||
}
|
||||
holder.appName.text = it.appName
|
||||
holder.pkgName.text = it.packageName
|
||||
holder.cbrName.text = "贡献者:" + it.contributorName
|
||||
@@ -158,6 +175,7 @@ class ConfigureActivity : BaseActivity() {
|
||||
lateinit var switchAll: MaterialSwitch
|
||||
}
|
||||
}.apply { onChanged = { notifyDataSetChanged() } }
|
||||
onScrollEvent = { post { setSelection(if (it) iconDatas.lastIndex else 0) } }
|
||||
}
|
||||
/** 设置点击事件 */
|
||||
findViewById<View>(R.id.config_cbr_button).setOnClickListener {
|
||||
@@ -169,7 +187,7 @@ class ConfigureActivity : BaseActivity() {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
})
|
||||
}.onFailure {
|
||||
Toast.makeText(this, "无法启动系统默认浏览器", Toast.LENGTH_SHORT).show()
|
||||
toast(msg = "无法启动系统默认浏览器")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -32,7 +32,6 @@ import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.widget.SwitchCompat
|
||||
import androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
import androidx.core.view.isVisible
|
||||
@@ -42,7 +41,7 @@ import com.fankes.miui.notify.hook.HookConst.ENABLE_COLOR_ICON_HOOK
|
||||
import com.fankes.miui.notify.hook.HookConst.ENABLE_HIDE_ICON
|
||||
import com.fankes.miui.notify.hook.HookConst.ENABLE_MODULE
|
||||
import com.fankes.miui.notify.hook.HookConst.ENABLE_MODULE_LOG
|
||||
import com.fankes.miui.notify.hook.HookConst.ENABLE_NOTIFY_ICON_HOOK
|
||||
import com.fankes.miui.notify.hook.HookConst.ENABLE_NOTIFY_ICON_FIX
|
||||
import com.fankes.miui.notify.ui.base.BaseActivity
|
||||
import com.fankes.miui.notify.utils.*
|
||||
import com.highcapable.yukihookapi.hook.factory.modulePrefs
|
||||
@@ -93,9 +92,9 @@ class MainActivity : BaseActivity() {
|
||||
noCancelable()
|
||||
}
|
||||
/** 判断是否 Hook */
|
||||
isHooked() -> {
|
||||
findViewById<LinearLayout>(R.id.main_lin_status).setBackgroundResource(R.drawable.green_round)
|
||||
findViewById<ImageFilterView>(R.id.main_img_status).setImageResource(R.mipmap.succcess)
|
||||
YukiHookModuleStatus.isActive() -> {
|
||||
findViewById<LinearLayout>(R.id.main_lin_status).setBackgroundResource(R.drawable.bg_green_round)
|
||||
findViewById<ImageFilterView>(R.id.main_img_status).setImageResource(R.mipmap.ic_success)
|
||||
findViewById<TextView>(R.id.main_text_status).text = "模块已激活"
|
||||
}
|
||||
else ->
|
||||
@@ -112,24 +111,29 @@ class MainActivity : BaseActivity() {
|
||||
/** 初始化 View */
|
||||
val moduleEnableSwitch = findViewById<SwitchCompat>(R.id.module_enable_switch)
|
||||
val moduleEnableLogSwitch = findViewById<SwitchCompat>(R.id.module_enable_log_switch)
|
||||
val colorIconHookItem = findViewById<View>(R.id.config_item_color_hook)
|
||||
val notifyIconConfigItem = findViewById<View>(R.id.config_item_notify)
|
||||
val hideIconInLauncherSwitch = findViewById<SwitchCompat>(R.id.hide_icon_in_launcher_switch)
|
||||
val colorIconHookSwitch = findViewById<SwitchCompat>(R.id.color_icon_fix_switch)
|
||||
val notifyIconHookSwitch = findViewById<SwitchCompat>(R.id.notify_icon_fix_switch)
|
||||
/** 设置旧版本警告 */
|
||||
findViewById<View>(R.id.config_notify_app_icon_warn).isVisible = miuiVersion == "12"
|
||||
val notifyIconFixSwitch = findViewById<SwitchCompat>(R.id.notify_icon_fix_switch)
|
||||
val notifyIconFixButton = findViewById<View>(R.id.config_notify_app_button)
|
||||
/** 获取 Sp 存储的信息 */
|
||||
notifyIconConfigItem.isVisible = modulePrefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)
|
||||
colorIconHookItem.isVisible = modulePrefs.getBoolean(ENABLE_MODULE, default = true)
|
||||
notifyIconConfigItem.isVisible = modulePrefs.getBoolean(ENABLE_MODULE, default = true) &&
|
||||
modulePrefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)
|
||||
moduleEnableLogSwitch.isVisible = modulePrefs.getBoolean(ENABLE_MODULE, default = true)
|
||||
notifyIconFixButton.isVisible = modulePrefs.getBoolean(ENABLE_NOTIFY_ICON_FIX, default = true)
|
||||
moduleEnableSwitch.isChecked = modulePrefs.getBoolean(ENABLE_MODULE, default = true)
|
||||
moduleEnableLogSwitch.isChecked = modulePrefs.getBoolean(ENABLE_MODULE_LOG, default = false)
|
||||
hideIconInLauncherSwitch.isChecked = modulePrefs.getBoolean(ENABLE_HIDE_ICON)
|
||||
colorIconHookSwitch.isChecked = modulePrefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)
|
||||
notifyIconHookSwitch.isChecked = modulePrefs.getBoolean(ENABLE_NOTIFY_ICON_HOOK, default = true)
|
||||
notifyIconFixSwitch.isChecked = modulePrefs.getBoolean(ENABLE_NOTIFY_ICON_FIX, default = true)
|
||||
moduleEnableSwitch.setOnCheckedChangeListener { btn, b ->
|
||||
if (!btn.isPressed) return@setOnCheckedChangeListener
|
||||
modulePrefs.putBoolean(ENABLE_MODULE, b)
|
||||
moduleEnableLogSwitch.isVisible = b
|
||||
colorIconHookItem.isVisible = b
|
||||
notifyIconConfigItem.isVisible = b && colorIconHookSwitch.isChecked
|
||||
SystemUITool.showNeedRestartSnake(context = this)
|
||||
}
|
||||
moduleEnableLogSwitch.setOnCheckedChangeListener { btn, b ->
|
||||
@@ -152,17 +156,16 @@ class MainActivity : BaseActivity() {
|
||||
notifyIconConfigItem.isVisible = b
|
||||
SystemUITool.showNeedRestartSnake(context = this)
|
||||
}
|
||||
notifyIconHookSwitch.setOnCheckedChangeListener { btn, b ->
|
||||
notifyIconFixSwitch.setOnCheckedChangeListener { btn, b ->
|
||||
if (!btn.isPressed) return@setOnCheckedChangeListener
|
||||
modulePrefs.putBoolean(ENABLE_NOTIFY_ICON_HOOK, b)
|
||||
modulePrefs.putBoolean(ENABLE_NOTIFY_ICON_FIX, b)
|
||||
notifyIconFixButton.isVisible = b
|
||||
SystemUITool.showNeedRestartSnake(context = this)
|
||||
}
|
||||
/** 通知图标优化名单按钮点击事件 */
|
||||
notifyIconFixButton.setOnClickListener { startActivity(Intent(this, ConfigureActivity::class.java)) }
|
||||
/** 重启按钮点击事件 */
|
||||
findViewById<View>(R.id.title_restart_icon).setOnClickListener { SystemUITool.restartSystemUI(context = this) }
|
||||
/** 通知图标优化名单按钮点击事件 */
|
||||
findViewById<View>(R.id.config_notify_app_button).setOnClickListener {
|
||||
startActivity(Intent(this, ConfigureActivity::class.java))
|
||||
}
|
||||
/** 恰饭! */
|
||||
findViewById<View>(R.id.link_with_follow_me).setOnClickListener {
|
||||
runCatching {
|
||||
@@ -174,7 +177,7 @@ class MainActivity : BaseActivity() {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
})
|
||||
}.onFailure {
|
||||
Toast.makeText(this, "你可能没有安装酷安", Toast.LENGTH_SHORT).show()
|
||||
toast(msg = "你可能没有安装酷安")
|
||||
}
|
||||
}
|
||||
/** 项目地址点击事件 */
|
||||
@@ -187,7 +190,7 @@ class MainActivity : BaseActivity() {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
})
|
||||
}.onFailure {
|
||||
Toast.makeText(this, "无法启动系统默认浏览器", Toast.LENGTH_SHORT).show()
|
||||
toast(msg = "无法启动系统默认浏览器")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -195,7 +198,7 @@ class MainActivity : BaseActivity() {
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
/** MIUI 12 的版本特殊 - 所以给出提示 */
|
||||
if (!isWarnDialogShowing && isHooked() && miuiVersion == "12" && isMiuiNotifyStyle)
|
||||
if (!isWarnDialogShowing && YukiHookModuleStatus.isActive() && miuiVersion == "12" && isMiuiNotifyStyle)
|
||||
showDialog {
|
||||
isWarnDialogShowing = true
|
||||
title = "经典通知栏样式已启用"
|
||||
@@ -205,10 +208,4 @@ class MainActivity : BaseActivity() {
|
||||
noCancelable()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断模块是否激活
|
||||
* @return [Boolean] 激活状态
|
||||
*/
|
||||
private fun isHooked() = YukiHookModuleStatus.isActive()
|
||||
}
|
@@ -22,11 +22,9 @@
|
||||
*/
|
||||
package com.fankes.miui.notify.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.widget.Toast
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus
|
||||
|
||||
/**
|
||||
* 系统界面工具
|
||||
@@ -46,7 +44,7 @@ object SystemUITool {
|
||||
execShellSu(cmd = "pgrep systemui").also { pid ->
|
||||
if (pid.isNotBlank())
|
||||
execShellSu(cmd = "kill -9 $pid")
|
||||
else Toast.makeText(context, "ROOT 权限获取失败", Toast.LENGTH_SHORT).show()
|
||||
else toast(msg = "ROOT 权限获取失败")
|
||||
}
|
||||
}
|
||||
cancelButton()
|
||||
@@ -57,9 +55,7 @@ object SystemUITool {
|
||||
* @param context 实例
|
||||
*/
|
||||
fun showNeedRestartSnake(context: Context) =
|
||||
Snackbar.make((context as Activity).findViewById(android.R.id.content), "设置需要重启系统界面才能生效", Snackbar.LENGTH_LONG)
|
||||
.apply {
|
||||
setActionTextColor(Color.WHITE)
|
||||
setAction("立即重启") { restartSystemUI(context) }
|
||||
}.show()
|
||||
if (YukiHookModuleStatus.isActive())
|
||||
context.snake(msg = "设置需要重启系统界面才能生效", actionText = "立即重启") { restartSystemUI(context) }
|
||||
else context.snake(msg = "模块没有激活,更改不会生效")
|
||||
}
|
@@ -20,10 +20,11 @@
|
||||
*
|
||||
* This file is Created by fankes on 2022/1/7.
|
||||
*/
|
||||
@file:Suppress("DEPRECATION", "PrivateApi", "unused")
|
||||
@file:Suppress("DEPRECATION", "PrivateApi", "unused", "ObsoleteSdkInt")
|
||||
|
||||
package com.fankes.miui.notify.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageInfo
|
||||
import android.content.pm.PackageManager
|
||||
@@ -32,10 +33,10 @@ import android.graphics.*
|
||||
import android.graphics.Bitmap.createBitmap
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
import android.service.notification.StatusBarNotification
|
||||
import android.util.Base64
|
||||
import android.widget.Toast
|
||||
import com.fankes.miui.notify.application.MNNApplication.Companion.appContext
|
||||
import com.highcapable.yukihookapi.hook.factory.callStatic
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.highcapable.yukihookapi.hook.factory.classOf
|
||||
import com.highcapable.yukihookapi.hook.factory.hasClass
|
||||
import com.highcapable.yukihookapi.hook.factory.method
|
||||
@@ -145,12 +146,6 @@ val miuiFullVersion
|
||||
get() = if (isMIUI) (miuiVersion + " " + findPropString(key = "ro.system.build.version.incremental"))
|
||||
else "不是 MIUI 系统"
|
||||
|
||||
/**
|
||||
* 获取推送通知的包名
|
||||
* @return [String]
|
||||
*/
|
||||
val StatusBarNotification.opPkgName get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) opPkg else packageName ?: ""
|
||||
|
||||
/**
|
||||
* 得到安装包信息
|
||||
* @return [PackageInfo]
|
||||
@@ -245,9 +240,10 @@ fun Bitmap.round(radius: Float): Bitmap =
|
||||
* @return [String]
|
||||
*/
|
||||
fun findPropString(key: String, default: String = "") = safeOf(default) {
|
||||
(classOf(name = "android.os.SystemProperties").method(
|
||||
name = "get", StringType, StringType
|
||||
)?.callStatic(key, default)) ?: default
|
||||
(classOf(name = "android.os.SystemProperties").method {
|
||||
name = "get"
|
||||
param(StringType, StringType)
|
||||
}.get().invoke(key, default)) ?: default
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -261,6 +257,26 @@ fun execShellSu(cmd: String) = safeOfNothing {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 弹出 [Toast]
|
||||
* @param msg 提示内容
|
||||
*/
|
||||
fun toast(msg: String) = Toast.makeText(appContext, msg, Toast.LENGTH_SHORT).show()
|
||||
|
||||
/**
|
||||
* 弹出 [Snackbar]
|
||||
* @param msg 提示内容
|
||||
* @param actionText 按钮文本 - 不写默认取消按钮
|
||||
* @param it 按钮事件回调
|
||||
*/
|
||||
fun Context.snake(msg: String, actionText: String = "", it: () -> Unit = {}) =
|
||||
Snackbar.make((this as Activity).findViewById(android.R.id.content), msg, Snackbar.LENGTH_LONG)
|
||||
.apply {
|
||||
if (actionText.isBlank()) return@apply
|
||||
setActionTextColor(Color.WHITE)
|
||||
setAction(actionText) { it() }
|
||||
}.show()
|
||||
|
||||
/**
|
||||
* 忽略异常返回值
|
||||
* @param it 回调 - 如果异常为空
|
||||
|
@@ -25,7 +25,7 @@
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="25dp"
|
||||
android:src="@mipmap/back"
|
||||
android:src="@mipmap/ic_back"
|
||||
android:tint="@color/colorTextGray"
|
||||
android:tooltipText="返回" />
|
||||
|
||||
@@ -57,12 +57,30 @@
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/config_title_up"
|
||||
android:layout_width="22dp"
|
||||
android:layout_height="22dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@mipmap/ic_page_top"
|
||||
android:tint="@color/colorTextGray"
|
||||
android:tooltipText="滚动到顶部" />
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/config_title_down"
|
||||
android:layout_width="22dp"
|
||||
android:layout_height="22dp"
|
||||
android:layout_marginEnd="17dp"
|
||||
android:src="@mipmap/ic_page_bottom"
|
||||
android:tint="@color/colorTextGray"
|
||||
android:tooltipText="滚动到底部" />
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/config_title_filter"
|
||||
android:layout_width="22dp"
|
||||
android:layout_height="22dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@mipmap/icon_filter"
|
||||
android:src="@mipmap/ic_filter"
|
||||
android:tint="@color/colorTextGray"
|
||||
android:tooltipText="按条件过滤" />
|
||||
</LinearLayout>
|
||||
@@ -73,7 +91,7 @@
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:background="@drawable/permotion_round"
|
||||
android:background="@drawable/bg_permotion_round"
|
||||
android:elevation="0dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
@@ -84,7 +102,7 @@
|
||||
android:layout_height="15dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:alpha="0.85"
|
||||
android:src="@mipmap/about"
|
||||
android:src="@mipmap/ic_about"
|
||||
android:tint="@color/colorTextDark" />
|
||||
|
||||
<TextView
|
||||
@@ -92,7 +110,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:alpha="0.6"
|
||||
android:lineSpacingExtra="5dp"
|
||||
android:text="启用替换后 APP 的彩色通知图标将被替换为预设的小图标。\n启用全部替换将忽略 APP 非彩色图标,强制将全部通知图标替换为列表中预设的小图标。"
|
||||
android:text="启用替换后 APP 的彩色通知图标将被替换为预设的小图标。\n启用全部替换将忽略 APP 单色图标,强制将全部通知图标替换为列表中预设的小图标。"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="11sp"
|
||||
tools:ignore="SmallSp" />
|
||||
@@ -133,7 +151,7 @@
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:background="@drawable/button_round"
|
||||
android:background="@drawable/bg_button_round"
|
||||
android:gravity="center"
|
||||
android:padding="10dp"
|
||||
android:singleLine="true"
|
||||
|
@@ -36,7 +36,7 @@
|
||||
android:layout_height="28dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:alpha="0.85"
|
||||
android:src="@mipmap/restart"
|
||||
android:src="@mipmap/ic_restart"
|
||||
android:tint="@color/colorTextGray"
|
||||
android:tooltipText="重启系统界面" />
|
||||
</LinearLayout>
|
||||
@@ -49,7 +49,7 @@
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:background="@drawable/dark_round"
|
||||
android:background="@drawable/bg_dark_round"
|
||||
android:elevation="0dp"
|
||||
android:gravity="center">
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
android:layout_height="25dp"
|
||||
android:layout_marginStart="25dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:src="@mipmap/warn"
|
||||
android:src="@mipmap/ic_warn"
|
||||
android:tint="@color/white" />
|
||||
|
||||
<LinearLayout
|
||||
@@ -121,7 +121,7 @@
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:background="@drawable/permotion_round"
|
||||
android:background="@drawable/bg_permotion_round"
|
||||
android:elevation="0dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
@@ -132,7 +132,7 @@
|
||||
android:layout_height="15dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:alpha="0.85"
|
||||
android:src="@mipmap/about"
|
||||
android:src="@mipmap/ic_about"
|
||||
android:tint="@color/colorTextDark" />
|
||||
|
||||
<TextView
|
||||
@@ -153,7 +153,7 @@
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:animateLayoutChanges="true"
|
||||
android:background="@drawable/permotion_round"
|
||||
android:background="@drawable/bg_permotion_round"
|
||||
android:elevation="0dp"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
@@ -184,18 +184,19 @@
|
||||
android:layout_marginBottom="10dp"
|
||||
android:alpha="0.6"
|
||||
android:lineSpacingExtra="6dp"
|
||||
android:text="模块关闭后功能都将彻底停止工作,以下选项都将不再生效。"
|
||||
android:text="模块关闭后一切功能都将彻底停止工作。"
|
||||
android:textColor="@color/colorTextDark"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/config_item_color_hook"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:background="@drawable/permotion_round"
|
||||
android:background="@drawable/bg_permotion_round"
|
||||
android:elevation="0dp"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
@@ -228,7 +229,8 @@
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:background="@drawable/permotion_round"
|
||||
android:animateLayoutChanges="true"
|
||||
android:background="@drawable/bg_permotion_round"
|
||||
android:elevation="0dp"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
@@ -250,7 +252,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:background="@drawable/button_round"
|
||||
android:background="@drawable/bg_button_round"
|
||||
android:gravity="center"
|
||||
android:padding="10dp"
|
||||
android:singleLine="true"
|
||||
@@ -266,23 +268,9 @@
|
||||
android:layout_marginBottom="10dp"
|
||||
android:alpha="0.6"
|
||||
android:lineSpacingExtra="6dp"
|
||||
android:text="此选项默认开启,开启后将对优化名单内 APP 通知小图标进行色彩修复,特别是通过 MIPUSH 推送的通知,它们始终是彩色的,修复后使得它们的图标看起来更加符合原生规范。"
|
||||
android:text="此选项默认开启,开启后将对优化名单内的 APP 通知小图标使用单色调进行修复,特别是通过 MIPUSH 推送的通知,它们始终是 APP 默认图标(彩色的 APP 图标),修复后使得它们的图标看起来更加符合 Android 原生的统一规范。"
|
||||
android:textColor="@color/colorTextDark"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/config_notify_app_icon_warn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:alpha="0.6"
|
||||
android:lineSpacingExtra="6dp"
|
||||
android:text="⚠️ 你的 MIUI 版本过低,状态栏上 MIPUSH 的彩色图标由于不能识别反色将不会被优化为黑白小图标,仅在通知栏生效。"
|
||||
android:textColor="#FF9800"
|
||||
android:textSize="12sp"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
@@ -291,7 +279,7 @@
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:background="@drawable/permotion_round"
|
||||
android:background="@drawable/bg_permotion_round"
|
||||
android:elevation="0dp"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
@@ -323,7 +311,7 @@
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:background="@drawable/permotion_round"
|
||||
android:background="@drawable/bg_permotion_round"
|
||||
android:elevation="0dp"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
@@ -340,7 +328,7 @@
|
||||
android:layout_height="15dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:alpha="0.85"
|
||||
android:src="@mipmap/about"
|
||||
android:src="@mipmap/ic_about"
|
||||
android:tint="@color/colorTextGray" />
|
||||
|
||||
<TextView
|
||||
@@ -400,7 +388,7 @@
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:background="@drawable/permotion_round"
|
||||
android:background="@drawable/bg_permotion_round"
|
||||
android:elevation="0dp"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
@@ -417,7 +405,7 @@
|
||||
android:layout_height="15dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:alpha="0.85"
|
||||
android:src="@mipmap/about"
|
||||
android:src="@mipmap/ic_about"
|
||||
android:tint="@color/colorTextGray" />
|
||||
|
||||
<TextView
|
||||
@@ -447,7 +435,7 @@
|
||||
android:layout_marginTop="15dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:background="@drawable/permotion_round"
|
||||
android:background="@drawable/bg_permotion_round"
|
||||
android:elevation="0dp"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
@@ -476,7 +464,7 @@
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@mipmap/qr_pay" />
|
||||
android:src="@mipmap/bg_qr_pay" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<TextView
|
||||
@@ -497,7 +485,7 @@
|
||||
android:layout_marginRight="15dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:autoLink="web"
|
||||
android:background="@drawable/permotion_round"
|
||||
android:background="@drawable/bg_permotion_round"
|
||||
android:lineSpacingExtra="6dp"
|
||||
android:padding="10dp"
|
||||
android:text="此模块使用 YukiHookAPI 构建。\n点击这里了解更多 https://github.com/fankes/YukiHookAPI"
|
||||
|
@@ -3,7 +3,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/permotion_round"
|
||||
android:background="@drawable/bg_permotion_round"
|
||||
android:baselineAligned="false"
|
||||
android:gravity="center|start"
|
||||
android:orientation="horizontal"
|
||||
@@ -28,7 +28,7 @@
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="15dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:src="@mipmap/about"
|
||||
android:src="@mipmap/ic_about"
|
||||
android:tint="@color/colorTextGray" />
|
||||
|
||||
<TextView
|
||||
|
Before Width: | Height: | Size: 201 KiB After Width: | Height: | Size: 201 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_filter.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.9 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_page_bottom.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_page_top.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
@@ -5,8 +5,8 @@ plugins {
|
||||
}
|
||||
|
||||
ext {
|
||||
appVersionName = "1.5"
|
||||
appVersionCode = 9
|
||||
appVersionName = "1.65"
|
||||
appVersionCode = 12
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
|
@@ -10,7 +10,8 @@ dependencyResolutionManagement {
|
||||
repositories {
|
||||
google()
|
||||
maven { url "https://api.xposed.info/" }
|
||||
maven { url 'https://www.jitpack.io' }
|
||||
maven { url "https://www.jitpack.io" }
|
||||
maven { url "https://s01.oss.sonatype.org/content/repositories/releases" }
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|