diff --git a/.idea/misc.xml b/.idea/misc.xml
index a0fd20c..4ef2cb8 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -8,6 +8,7 @@
+
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 654d45f..a6b334e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -4,7 +4,7 @@
package="com.fankes.miui.notify">
@@ -53,5 +52,10 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/fankes/miui/notify/application/MNvApplication.kt b/app/src/main/java/com/fankes/miui/notify/application/MNNApplication.kt
similarity index 86%
rename from app/src/main/java/com/fankes/miui/notify/application/MNvApplication.kt
rename to app/src/main/java/com/fankes/miui/notify/application/MNNApplication.kt
index bf9b741..1310463 100644
--- a/app/src/main/java/com/fankes/miui/notify/application/MNvApplication.kt
+++ b/app/src/main/java/com/fankes/miui/notify/application/MNNApplication.kt
@@ -25,19 +25,24 @@ package com.fankes.miui.notify.application
import android.app.Application
import androidx.appcompat.app.AppCompatDelegate
-class MNvApplication : Application() {
+class MNNApplication : Application() {
companion object {
/** 全局静态实例 */
- private var context: MNvApplication? = null
+ private var context: MNNApplication? = null
/** 调用全局静态实例 */
val appContext get() = context ?: error("App is death")
+
+ /** 自身 APP 是否已启动 */
+ var isMineStarted = false
}
override fun onCreate() {
super.onCreate()
+ /** 设置状态 */
+ isMineStarted = true
/** 设置静态实例 */
context = this
/** 跟随系统夜间模式 */
diff --git a/app/src/main/java/com/fankes/miui/notify/bean/IconDataBean.kt b/app/src/main/java/com/fankes/miui/notify/bean/IconDataBean.kt
new file mode 100644
index 0000000..aae8fe9
--- /dev/null
+++ b/app/src/main/java/com/fankes/miui/notify/bean/IconDataBean.kt
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 2022. Fankes Studio(qzmmcn@163.com)
+ *
+ * This file is part of MIUINativeNotifyIcon.
+ *
+ * MIUINativeNotifyIcon is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MIUINativeNotifyIcon 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * This file is Created by fankes on 2022/1/30.
+ */
+package com.fankes.miui.notify.bean
+
+import android.graphics.Bitmap
+import java.io.Serializable
+
+/**
+ * 通知栏小图标 bean
+ * @param appName APP 名称 - 仅限默认语言区域
+ * @param packageName 包名
+ * @param iconBitmap 图标位图
+ * @param contributorName 贡献者昵称
+ */
+data class IconDataBean(
+ var appName: String,
+ var packageName: String,
+ var iconBitmap: Bitmap,
+ var contributorName: String
+) : Serializable
\ No newline at end of file
diff --git a/app/src/main/java/com/fankes/miui/notify/hook/HookMain.kt b/app/src/main/java/com/fankes/miui/notify/hook/HookMain.kt
index ca16dbc..65c0c03 100644
--- a/app/src/main/java/com/fankes/miui/notify/hook/HookMain.kt
+++ b/app/src/main/java/com/fankes/miui/notify/hook/HookMain.kt
@@ -23,6 +23,7 @@
package com.fankes.miui.notify.hook
import android.content.Context
+import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.Outline
import android.graphics.drawable.Drawable
@@ -33,11 +34,10 @@ import android.view.View
import android.view.ViewOutlineProvider
import android.widget.ImageView
import androidx.annotation.Keep
-import androidx.core.app.NotificationCompat
import androidx.core.graphics.drawable.toBitmap
-import com.fankes.miui.notify.hook.HookMedium.QQ_PACKAGE_NAME
import com.fankes.miui.notify.hook.HookMedium.SELF_PACKAGE_NAME
import com.fankes.miui.notify.hook.HookMedium.SYSTEMUI_PACKAGE_NAME
+import com.fankes.miui.notify.params.IconPackParams
import com.fankes.miui.notify.utils.*
import de.robv.android.xposed.*
import de.robv.android.xposed.callbacks.XC_LoadPackage
@@ -142,6 +142,17 @@ class HookMain : IXposedHookLoadPackage {
.apply { isAccessible = true }.invoke(instance, icon) as Boolean
}
+ /**
+ * 获取 [ExpandedNotificationClass] 的应用名称
+ * @param instance 通知实例
+ * @return [String]
+ */
+ private fun XC_LoadPackage.LoadPackageParam.findAppName(instance: Any?) =
+ findClass(ExpandedNotificationClass).getDeclaredMethod("getAppName").let {
+ it.isAccessible = true
+ it.invoke(instance) as? String ?: ""
+ }
+
/**
* 获取全局上下文
* @return [Context]
@@ -162,15 +173,23 @@ class HookMain : IXposedHookLoadPackage {
val iconDrawable = (param.result as Icon).loadDrawable(globalContext)
/** 获取通知对象 - 由于 MIUI 的版本迭代不规范性可能是空的 */
(param.args?.get(0) as? StatusBarNotification?)?.also { notifyInstance ->
- /** 判断要设置的图标 */
+ /** 目标彩色通知 APP 图标 */
+ var customIcon: Icon? = null
+ run {
+ IconPackParams.iconDatas.forEach {
+ if ((notifyInstance.opPkgName == it.packageName ||
+ findAppName(notifyInstance) == it.appName) &&
+ HookMedium.isAppNotifyHookOf(it.packageName)
+ ) {
+ customIcon = Icon.createWithBitmap(it.iconBitmap)
+ return@run
+ }
+ }
+ }
when {
- /** 如果开启了修复聊天 APP 的图标 */
- notifyInstance.opPkgName == QQ_PACKAGE_NAME &&
- XPrefUtils.getBoolean(
- HookMedium.ENABLE_CHAT_ICON_HOOK,
- default = true
- ) ->
- param.result = Icon.createWithBitmap(IconPackParams.qqSmallIcon)
+ /** 如果开启了修复 APP 的彩色图标 */
+ customIcon != null && HookMedium.getBoolean(HookMedium.ENABLE_NOTIFY_ICON_HOOK, default = true) ->
+ param.result = customIcon
/** 若不是灰度图标自动处理为圆角 */
!isGrayscaleIcon(globalContext, iconDrawable) ->
param.result = Icon.createWithBitmap(
@@ -205,15 +224,24 @@ class HookMain : IXposedHookLoadPackage {
/** 获取通知小图标 */
val iconDrawable = notifyInstance.notification.smallIcon.loadDrawable(context)
- /** 获取发送通知的 APP */
- val packageName = notifyInstance.opPkgName
- /** 如果开启了修复聊天 APP 的图标 */
- if (packageName == QQ_PACKAGE_NAME &&
- XPrefUtils.getBoolean(HookMedium.ENABLE_CHAT_ICON_HOOK, default = true)
- )
+ /** 自定义默认小图标 */
+ var customIcon: Bitmap? = null
+ run {
+ IconPackParams.iconDatas.forEach {
+ if ((notifyInstance.opPkgName == it.packageName ||
+ findAppName(notifyInstance) == it.appName) &&
+ HookMedium.isAppNotifyHookOf(it.packageName)
+ ) {
+ customIcon = it.iconBitmap
+ return@run
+ }
+ }
+ }
+ /** 如果开启了修复 APP 的彩色图标 */
+ if (customIcon != null && HookMedium.getBoolean(HookMedium.ENABLE_NOTIFY_ICON_HOOK, default = true))
iconImageView.apply {
/** 设置自定义小图标 */
- setImageBitmap(IconPackParams.qqSmallIcon)
+ setImageBitmap(customIcon)
/** 上色 */
setColorFilter(if (isUpperOfAndroidS) newStyle else oldStyle)
}
@@ -265,7 +293,7 @@ class HookMain : IXposedHookLoadPackage {
/** 系统版本过低直接停止 Hook */
if (isLowerAndroidP) return
/** 若没开启模块直接停止 Hook */
- if (!XPrefUtils.getBoolean(HookMedium.ENABLE_MODULE, default = true)) return
+ if (!HookMedium.getBoolean(HookMedium.ENABLE_MODULE, default = true)) return
/** 强制回写系统的状态栏图标样式为原生 */
runWithoutError(error = "SubstituteSmallIcon") {
XposedHelpers.findAndHookMethod(
@@ -285,19 +313,30 @@ class HookMain : IXposedHookLoadPackage {
lpparam.findClass(ExpandedNotificationClass),
object : XC_MethodReplacement() {
override fun replaceHookedMethod(param: MethodHookParam) =
- if (XPrefUtils.getBoolean(HookMedium.ENABLE_COLOR_ICON_HOOK, default = true))
+ if (HookMedium.getBoolean(HookMedium.ENABLE_COLOR_ICON_HOOK, default = true))
try {
/** 获取通知对象 - 由于 MIUI 的版本迭代不规范性可能是空的 */
(param.args?.get(0) as? StatusBarNotification?)?.let { notifyInstance ->
- /** 获取发送通知的 APP */
- val packageName = notifyInstance.opPkgName
- NotificationCompat()
/** 获取通知小图标 */
val iconDrawable =
notifyInstance.notification.smallIcon.loadDrawable(lpparam.globalContext)
- /** 如果开启了修复聊天 APP 的图标 */
- if (packageName == QQ_PACKAGE_NAME &&
- XPrefUtils.getBoolean(HookMedium.ENABLE_CHAT_ICON_HOOK, default = true)
+
+ /** 获取目标修复彩色图标的 APP */
+ var isTargetApp = false
+ run {
+ IconPackParams.iconDatas.forEach {
+ if ((notifyInstance.opPkgName == it.packageName ||
+ lpparam.findAppName(notifyInstance) == it.appName) &&
+ HookMedium.isAppNotifyHookOf(it.packageName)
+ ) {
+ isTargetApp = true
+ return@run
+ }
+ }
+ }
+ /** 如果开启了修复 APP 的彩色图标 */
+ if (isTargetApp &&
+ HookMedium.getBoolean(HookMedium.ENABLE_NOTIFY_ICON_HOOK, default = true)
) false
/** 只要不是灰度就返回彩色图标 */
else !lpparam.isGrayscaleIcon(lpparam.globalContext, iconDrawable)
diff --git a/app/src/main/java/com/fankes/miui/notify/hook/HookMedium.kt b/app/src/main/java/com/fankes/miui/notify/hook/HookMedium.kt
index 98b3703..3d0342f 100644
--- a/app/src/main/java/com/fankes/miui/notify/hook/HookMedium.kt
+++ b/app/src/main/java/com/fankes/miui/notify/hook/HookMedium.kt
@@ -18,10 +18,20 @@
*
* This file is Created by fankes on 2022/1/24.
*/
+@file:Suppress("DEPRECATION", "SetWorldReadable")
+
package com.fankes.miui.notify.hook
+import android.content.Context
+import android.os.Handler
import android.util.Log
+import android.widget.Toast
import androidx.annotation.Keep
+import com.fankes.miui.notify.application.MNNApplication.Companion.appContext
+import com.fankes.miui.notify.application.MNNApplication.Companion.isMineStarted
+import com.fankes.miui.notify.utils.FileUtils
+import com.fankes.miui.notify.utils.XPrefUtils
+import java.io.File
@Keep
object HookMedium {
@@ -29,11 +39,10 @@ object HookMedium {
const val ENABLE_MODULE = "_enable_module"
const val ENABLE_HIDE_ICON = "_hide_icon"
const val ENABLE_COLOR_ICON_HOOK = "_color_icon_hook"
- const val ENABLE_CHAT_ICON_HOOK = "_chat_icon_hook"
+ const val ENABLE_NOTIFY_ICON_HOOK = "_notify_icon_hook"
const val SELF_PACKAGE_NAME = "com.fankes.miui.notify"
const val SYSTEMUI_PACKAGE_NAME = "com.android.systemui"
- const val QQ_PACKAGE_NAME = "com.tencent.mobileqq"
/**
* 判断模块是否激活
@@ -44,4 +53,70 @@ object HookMedium {
Log.d("MIUINativeNotifyIcon", "isHooked: true")
return false
}
+
+ /**
+ * 获取此 APP 的通知图标是否被 Hook
+ * @param packageName 包名
+ */
+ fun isAppNotifyHookOf(packageName: String) = getBoolean(key = "${packageName}_icon", default = true)
+
+ /**
+ * 设置 Hook 此 APP 的通知图标
+ * @param packageName 包名
+ * @param isHook 是否 Hook
+ */
+ fun putAppNotifyHookOf(packageName: String, isHook: Boolean) = putBoolean(key = "${packageName}_icon", bool = isHook)
+
+ /**
+ * 获取保存的值
+ * @param key 名称
+ * @param default 默认值
+ * @return [Boolean] 保存的值
+ */
+ fun getBoolean(key: String, default: Boolean = false) =
+ if (isMineStarted)
+ appContext.getSharedPreferences(
+ appContext.packageName + "_preferences",
+ Context.MODE_PRIVATE
+ ).getBoolean(key, default)
+ else XPrefUtils.getBoolean(key, default)
+
+ /**
+ * 保存值
+ * @param key 名称
+ * @param bool 值
+ */
+ fun putBoolean(key: String, bool: Boolean) {
+ appContext.getSharedPreferences(
+ appContext.packageName + "_preferences",
+ Context.MODE_PRIVATE
+ ).edit().putBoolean(key, bool).apply()
+ setWorldReadable(appContext)
+ /** 延迟继续设置强制允许 SP 可读可写 */
+ Handler().postDelayed({ setWorldReadable(appContext) }, 500)
+ Handler().postDelayed({ setWorldReadable(appContext) }, 1000)
+ Handler().postDelayed({ setWorldReadable(appContext) }, 1500)
+ }
+
+ /**
+ * 强制设置 Sp 存储为全局可读可写
+ * 以供模块使用
+ * @param context 实例
+ */
+ fun setWorldReadable(context: Context) {
+ try {
+ if (FileUtils.getDefaultPrefFile(context).exists()) {
+ for (file in arrayOf(
+ FileUtils.getDataDir(context),
+ FileUtils.getPrefDir(context),
+ FileUtils.getDefaultPrefFile(context)
+ )) {
+ file.setReadable(true, false)
+ file.setExecutable(true, false)
+ }
+ }
+ } catch (_: Exception) {
+ Toast.makeText(context, "无法写入模块设置,请检查权限\n如果此提示一直显示,请不要双开模块", Toast.LENGTH_SHORT).show()
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/fankes/miui/notify/hook/IconPackParams.kt b/app/src/main/java/com/fankes/miui/notify/hook/IconPackParams.kt
deleted file mode 100644
index 2cb9cdd..0000000
--- a/app/src/main/java/com/fankes/miui/notify/hook/IconPackParams.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * Copyright (C) 2022. Fankes Studio(qzmmcn@163.com)
- *
- * This file is part of MIUINativeNotifyIcon.
- *
- * MIUINativeNotifyIcon is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * MIUINativeNotifyIcon 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- * This file is Created by fankes on 2022/1/24.
- */
-package com.fankes.miui.notify.hook
-
-import android.graphics.Bitmap
-import com.fankes.miui.notify.utils.bitmap
-import com.fankes.miui.notify.utils.unbase64
-
-object IconPackParams {
-
- /**
- * QQ 通知栏小图标
- * @return [Bitmap]
- */
- val qqSmallIcon by lazy {
- ("iVBORw0KGgoAAAANSUhEUgAAAEwAAABMCAYAAADHl1ErAAAAAXNSR0IArs4c6QAAAARzQklUCAgI\n" +
- "CHwIZIgAAATZSURBVHic7ZxNjF5TGMd/T6uliBk1pSgtxQwlqo2gKghiU4ZaCOIjRGwIiY8QCRs7\n" +
- "S4suRJBYkUgXMiIipBYTiZmuKtRHW0biK8xrNE2l9be4d5LpeN/33nue877n3tHf5p259zzPfc4/\n" +
- "z7kf5wuOUglLeXFJw8BmYD0wApwBrACW5UUOANPAPuAb4HNg0sx29j/aREgakvSUpHGFMyHpBUln\n" +
- "p65Pz5C0VNJLkmYcQs3nkKRtkoZS1y8qkkYl/RBRqPlMS3oodT2jIOnlHgo1nzdT19eFpHf6KNYs\n" +
- "O1LXO4hEYs0ynrr+lZD0SkKxZtmeWodSSLoztVJzeC52/aK+uEoaBP6I6TMC55nZt7GcLYrlKOeN\n" +
- "yP5i8HZMZ9EEk7QRGI3lLyIbJG2N5Sxak1T2ZLoylr/ITJnZWTEcRckwSeuor1gAqyTdHMNRrCb5\n" +
- "TCQ/veT5GE7cTVLSUuBP4Fh/OD1npZn97HEQI8O20AyxAO71OoghWB2fjJ1w38diNMk9wBqvnz5x\n" +
- "EDjFzPaHOnBlmLIu5qaIBdmtY7PHgbdJXu60T8ElHmOvYCNO+xQkFWzYaZ+CCzzGXsHOddqnYK2k\n" +
- "4HoHG+YXPTXUPiHLycY+g/Bk2EnAoMM+FYtxxO0V7ESHfUqODzX0CLbEYZua40INY/e4LniOClYR\n" +
- "j2CtaFH0n99DDT2CneawTU3w969HsEcdtql5PNQwqHunYb2snQjqfQ3NsNtptlgAD4YYhWZYnYfU\n" +
- "yhI09FY5wyStpfliQTb0dm1Vo5Am+USATV15sqpBpSaZ91C0aO43ZDtWmNlvZQtXzbC7WVhiATxc\n" +
- "pXDVDNsBXFMpnPqz18zOKVu4tGDK5sTvCwqp/mwys1LTPKs0yXsCg2kC95UtWCXDdgPnB4VTf/4C\n" +
- "Bszsn6KCpTIsn860UMWC7EF2U5mCZZvkXeGxNIb7yxQq1SQXeHOcpWVmhYMjhRmWPx0XulgAA2U+\n" +
- "lco0ySZNZ/JyS1GBMoLdECGQpnB9UYGu97D82/EnHCPFDaTrt2VRhl3G/0ssgKu7nSwSbH3EQJrC\n" +
- "pd1OFgl2YYfjh4GpoHDqwRTZ9M12dJ0/ViTYRR2OPwK8WmBbZ94j66pqR6ckAYoFW93m2F4ze61M\n" +
- "VDVmwMzeBT5tc25VN8Miwdrd8Lfkvz+WCKyufJf/tlu0tbibYZFgy+b9/7SZ7cr//qREYHXlQ4D8\n" +
- "9eGOaF515B4T/1kSLGl3j1fU9oIZZQPRc+sxd8n1TDdNijLsQP47aWa3tTn/eoF9HXnLzP6ee8DM\n" +
- "HgPez//tOmZR9Ka/DVgH3Dj/Ivn5IeDXSuGmZ8TMvmp3QtIYcMjMbu3Z1VWPHQTKMuatb4y1RieQ\n" +
- "jVV2fbrUhNVm9r3HgXsGYr7Q6QGvnz7wolcsiLvmezv17TubNLONMRzFFGwR8CX1651tAWvMbDqG\n" +
- "s2iTgvMhqk3U66P8IHBFLLGgR1v6SZoANvTCdwW+Bi5u9zrk4ZiYziRdBVxHPWYnLgGelfSZmX2Q\n" +
- "OpgjkLRV0sfpXq8KmVAddrCTNChpLLEYVRhXNoMymOB7mLIX1p3U76lYRAsYDt2/wvOUXEnzxAIY\n" +
- "wLH02nPT30O2ccYoWVf2mYR/Hh0m23dsP9myltlXk9PJlhkuB052+v8F+AL4CGjWln9N5l/CCEZS\n" +
- "HWRiiAAAAABJRU5ErkJggg==").unbase64.bitmap
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/fankes/miui/notify/params/IconPackParams.kt b/app/src/main/java/com/fankes/miui/notify/params/IconPackParams.kt
new file mode 100644
index 0000000..4b44693
--- /dev/null
+++ b/app/src/main/java/com/fankes/miui/notify/params/IconPackParams.kt
@@ -0,0 +1,70 @@
+/**
+ * Copyright (C) 2022. Fankes Studio(qzmmcn@163.com)
+ *
+ * This file is part of MIUINativeNotifyIcon.
+ *
+ * MIUINativeNotifyIcon is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MIUINativeNotifyIcon 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * This file is Created by fankes on 2022/1/24.
+ */
+package com.fankes.miui.notify.params
+
+import com.fankes.miui.notify.bean.IconDataBean
+import com.fankes.miui.notify.utils.bitmap
+
+/**
+ * 通知栏小图标适配类
+ * 国内 APP 不规范的图标将由这里完成其自定义黑白小图标绘制
+ */
+object IconPackParams {
+
+ /**
+ * 通知栏小图标数组
+ * 默认使用包名进行匹配 - 若失败则使用 APP 名称进行匹配
+ * @return [Array]
+ */
+ val iconDatas by lazy {
+ arrayOf(
+ IconDataBean(
+ appName = "QQ",
+ packageName = "com.tencent.mobileqq",
+ iconBitmap = ("iVBORw0KGgoAAAANSUhEUgAAAEwAAABMCAYAAADHl1ErAAAAAXNSR0IArs4c6QAAAARzQklUCAgI\n" +
+ "CHwIZIgAAATZSURBVHic7ZxNjF5TGMd/T6uliBk1pSgtxQwlqo2gKghiU4ZaCOIjRGwIiY8QCRs7\n" +
+ "S4suRJBYkUgXMiIipBYTiZmuKtRHW0biK8xrNE2l9be4d5LpeN/33nue877n3tHf5p259zzPfc4/\n" +
+ "z7kf5wuOUglLeXFJw8BmYD0wApwBrACW5UUOANPAPuAb4HNg0sx29j/aREgakvSUpHGFMyHpBUln\n" +
+ "p65Pz5C0VNJLkmYcQs3nkKRtkoZS1y8qkkYl/RBRqPlMS3oodT2jIOnlHgo1nzdT19eFpHf6KNYs\n" +
+ "O1LXO4hEYs0ynrr+lZD0SkKxZtmeWodSSLoztVJzeC52/aK+uEoaBP6I6TMC55nZt7GcLYrlKOeN\n" +
+ "yP5i8HZMZ9EEk7QRGI3lLyIbJG2N5Sxak1T2ZLoylr/ITJnZWTEcRckwSeuor1gAqyTdHMNRrCb5\n" +
+ "TCQ/veT5GE7cTVLSUuBP4Fh/OD1npZn97HEQI8O20AyxAO71OoghWB2fjJ1w38diNMk9wBqvnz5x\n" +
+ "EDjFzPaHOnBlmLIu5qaIBdmtY7PHgbdJXu60T8ElHmOvYCNO+xQkFWzYaZ+CCzzGXsHOddqnYK2k\n" +
+ "4HoHG+YXPTXUPiHLycY+g/Bk2EnAoMM+FYtxxO0V7ESHfUqODzX0CLbEYZua40INY/e4LniOClYR\n" +
+ "j2CtaFH0n99DDT2CneawTU3w969HsEcdtql5PNQwqHunYb2snQjqfQ3NsNtptlgAD4YYhWZYnYfU\n" +
+ "yhI09FY5wyStpfliQTb0dm1Vo5Am+USATV15sqpBpSaZ91C0aO43ZDtWmNlvZQtXzbC7WVhiATxc\n" +
+ "pXDVDNsBXFMpnPqz18zOKVu4tGDK5sTvCwqp/mwys1LTPKs0yXsCg2kC95UtWCXDdgPnB4VTf/4C\n" +
+ "Bszsn6KCpTIsn860UMWC7EF2U5mCZZvkXeGxNIb7yxQq1SQXeHOcpWVmhYMjhRmWPx0XulgAA2U+\n" +
+ "lco0ySZNZ/JyS1GBMoLdECGQpnB9UYGu97D82/EnHCPFDaTrt2VRhl3G/0ssgKu7nSwSbH3EQJrC\n" +
+ "pd1OFgl2YYfjh4GpoHDqwRTZ9M12dJ0/ViTYRR2OPwK8WmBbZ94j66pqR6ckAYoFW93m2F4ze61M\n" +
+ "VDVmwMzeBT5tc25VN8Miwdrd8Lfkvz+WCKyufJf/tlu0tbibYZFgy+b9/7SZ7cr//qREYHXlQ4D8\n" +
+ "9eGOaF515B4T/1kSLGl3j1fU9oIZZQPRc+sxd8n1TDdNijLsQP47aWa3tTn/eoF9HXnLzP6ee8DM\n" +
+ "HgPez//tOmZR9Ka/DVgH3Dj/Ivn5IeDXSuGmZ8TMvmp3QtIYcMjMbu3Z1VWPHQTKMuatb4y1RieQ\n" +
+ "jVV2fbrUhNVm9r3HgXsGYr7Q6QGvnz7wolcsiLvmezv17TubNLONMRzFFGwR8CX1651tAWvMbDqG\n" +
+ "s2iTgvMhqk3U66P8IHBFLLGgR1v6SZoANvTCdwW+Bi5u9zrk4ZiYziRdBVxHPWYnLgGelfSZmX2Q\n" +
+ "OpgjkLRV0sfpXq8KmVAddrCTNChpLLEYVRhXNoMymOB7mLIX1p3U76lYRAsYDt2/wvOUXEnzxAIY\n" +
+ "wLH02nPT30O2ccYoWVf2mYR/Hh0m23dsP9myltlXk9PJlhkuB052+v8F+AL4CGjWln9N5l/CCEZS\n" +
+ "HWRiiAAAAABJRU5ErkJggg==").bitmap,
+ contributorName = "fankes"
+ )
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/fankes/miui/notify/ui/ConfigureActivity.kt b/app/src/main/java/com/fankes/miui/notify/ui/ConfigureActivity.kt
new file mode 100644
index 0000000..7a77716
--- /dev/null
+++ b/app/src/main/java/com/fankes/miui/notify/ui/ConfigureActivity.kt
@@ -0,0 +1,36 @@
+/**
+ * Copyright (C) 2022. Fankes Studio(qzmmcn@163.com)
+ *
+ * This file is part of MIUINativeNotifyIcon.
+ *
+ * MIUINativeNotifyIcon is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MIUINativeNotifyIcon 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * This file is Created by fankes on 2022/01/30.
+ */
+package com.fankes.miui.notify.ui
+
+import android.os.Bundle
+import android.view.View
+import com.fankes.miui.notify.R
+import com.fankes.miui.notify.ui.base.BaseActivity
+
+class ConfigureActivity : BaseActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_config)
+ /** 返回按钮点击事件 */
+ findViewById(R.id.title_back_icon).setOnClickListener { onBackPressed() }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/fankes/miui/notify/ui/MainActivity.kt b/app/src/main/java/com/fankes/miui/notify/ui/MainActivity.kt
index a2f934b..3eb957e 100644
--- a/app/src/main/java/com/fankes/miui/notify/ui/MainActivity.kt
+++ b/app/src/main/java/com/fankes/miui/notify/ui/MainActivity.kt
@@ -18,32 +18,28 @@
*
* This file is Created by fankes on 2022/01/24.
*/
-@file:Suppress("DEPRECATION", "SetWorldReadable", "SetTextI18n")
+@file:Suppress("SetTextI18n")
package com.fankes.miui.notify.ui
import android.content.ComponentName
-import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle
-import android.os.Handler
import android.view.View
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
-import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SwitchCompat
import androidx.constraintlayout.utils.widget.ImageFilterView
import com.fankes.miui.notify.BuildConfig
import com.fankes.miui.notify.R
import com.fankes.miui.notify.hook.HookMedium
+import com.fankes.miui.notify.ui.base.BaseActivity
import com.fankes.miui.notify.utils.*
-import com.gyf.immersionbar.ktx.immersionBar
-import java.io.File
-class MainActivity : AppCompatActivity() {
+class MainActivity : BaseActivity() {
companion object {
@@ -54,17 +50,6 @@ class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
- /** 隐藏系统的标题栏 */
- supportActionBar?.hide()
- /** 初始化沉浸状态栏 */
- immersionBar {
- statusBarColor(R.color.colorThemeBackground)
- autoDarkModeEnable(true)
- statusBarDarkFont(isNotSystemInDarkMode)
- navigationBarColor(R.color.colorThemeBackground)
- navigationBarDarkIcon(isNotSystemInDarkMode)
- fitsSystemWindows(true)
- }
/** 设置文本 */
findViewById(R.id.main_text_version).text = "当前版本:$moduleVersion"
findViewById(R.id.main_text_miui_version).text = "MIUI 版本:$miuiVersion"
@@ -108,12 +93,12 @@ class MainActivity : AppCompatActivity() {
val moduleEnableSwitch = findViewById(R.id.module_enable_switch)
val hideIconInLauncherSwitch = findViewById(R.id.hide_icon_in_launcher_switch)
val colorIconHookSwitch = findViewById(R.id.color_icon_fix_switch)
- val chatIconHookSwitch = findViewById(R.id.chat_icon_fix_switch)
+ val notifyIconHookSwitch = findViewById(R.id.notify_icon_fix_switch)
/** 获取 Sp 存储的信息 */
moduleEnableSwitch.isChecked = getBoolean(HookMedium.ENABLE_MODULE, default = true)
hideIconInLauncherSwitch.isChecked = getBoolean(HookMedium.ENABLE_HIDE_ICON)
colorIconHookSwitch.isChecked = getBoolean(HookMedium.ENABLE_COLOR_ICON_HOOK, default = true)
- chatIconHookSwitch.isChecked = getBoolean(HookMedium.ENABLE_CHAT_ICON_HOOK, default = true)
+ notifyIconHookSwitch.isChecked = getBoolean(HookMedium.ENABLE_NOTIFY_ICON_HOOK, default = true)
moduleEnableSwitch.setOnCheckedChangeListener { btn, b ->
if (!btn.isPressed) return@setOnCheckedChangeListener
putBoolean(HookMedium.ENABLE_MODULE, b)
@@ -131,9 +116,9 @@ class MainActivity : AppCompatActivity() {
if (!btn.isPressed) return@setOnCheckedChangeListener
putBoolean(HookMedium.ENABLE_COLOR_ICON_HOOK, b)
}
- chatIconHookSwitch.setOnCheckedChangeListener { btn, b ->
+ notifyIconHookSwitch.setOnCheckedChangeListener { btn, b ->
if (!btn.isPressed) return@setOnCheckedChangeListener
- putBoolean(HookMedium.ENABLE_CHAT_ICON_HOOK, b)
+ putBoolean(HookMedium.ENABLE_NOTIFY_ICON_HOOK, b)
}
/** 重启按钮点击事件 */
findViewById(R.id.title_restart_icon).setOnClickListener {
@@ -144,6 +129,10 @@ class MainActivity : AppCompatActivity() {
cancelButton()
}
}
+ /** 通知图标优化名单按钮点击事件 */
+ findViewById(R.id.config_notify_app_button).setOnClickListener {
+ startActivity(Intent(this, ConfigureActivity::class.java))
+ }
/** 恰饭! */
findViewById(R.id.link_with_follow_me).setOnClickListener {
try {
@@ -187,73 +176,18 @@ class MainActivity : AppCompatActivity() {
else Toast.makeText(this, "ROOT 权限获取失败", Toast.LENGTH_SHORT).show()
}
- override fun onResume() {
- super.onResume()
- setWorldReadable()
- }
-
- override fun onRestart() {
- super.onRestart()
- setWorldReadable()
- }
-
- override fun onPause() {
- super.onPause()
- setWorldReadable()
- }
-
/**
* 获取保存的值
* @param key 名称
* @param default 默认值
* @return [Boolean] 保存的值
*/
- private fun getBoolean(key: String, default: Boolean = false) =
- getSharedPreferences(
- packageName + "_preferences",
- Context.MODE_PRIVATE
- ).getBoolean(key, default)
+ private fun getBoolean(key: String, default: Boolean = false) = HookMedium.getBoolean(key, default)
/**
* 保存值
* @param key 名称
* @param bool 值
*/
- private fun putBoolean(key: String, bool: Boolean) {
- getSharedPreferences(
- packageName + "_preferences",
- Context.MODE_PRIVATE
- ).edit().putBoolean(key, bool).apply()
- setWorldReadable()
- /** 延迟继续设置强制允许 SP 可读可写 */
- Handler().postDelayed({ setWorldReadable() }, 500)
- Handler().postDelayed({ setWorldReadable() }, 1000)
- Handler().postDelayed({ setWorldReadable() }, 1500)
- }
-
- /**
- * 强制设置 Sp 存储为全局可读可写
- * 以供模块使用
- */
- private fun setWorldReadable() {
- try {
- if (FileUtils.getDefaultPrefFile(this).exists()) {
- for (file in arrayOf(
- FileUtils.getDataDir(this),
- FileUtils.getPrefDir(this),
- FileUtils.getDefaultPrefFile(this)
- )) {
- file.setReadable(true, false)
- file.setExecutable(true, false)
- }
- }
- } catch (_: Exception) {
- Toast.makeText(this, "无法写入模块设置,请检查权限\n如果此提示一直显示,请不要双开模块", Toast.LENGTH_SHORT).show()
- }
- }
-
- override fun onBackPressed() {
- setWorldReadable()
- super.onBackPressed()
- }
+ private fun putBoolean(key: String, bool: Boolean) = HookMedium.putBoolean(key, bool)
}
\ No newline at end of file
diff --git a/app/src/main/java/com/fankes/miui/notify/ui/base/BaseActivity.kt b/app/src/main/java/com/fankes/miui/notify/ui/base/BaseActivity.kt
new file mode 100644
index 0000000..b9652ea
--- /dev/null
+++ b/app/src/main/java/com/fankes/miui/notify/ui/base/BaseActivity.kt
@@ -0,0 +1,66 @@
+/**
+ * Copyright (C) 2022. Fankes Studio(qzmmcn@163.com)
+ *
+ * This file is part of MIUINativeNotifyIcon.
+ *
+ * MIUINativeNotifyIcon is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * MIUINativeNotifyIcon 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * This file is Created by fankes on 2022/01/30.
+ */
+package com.fankes.miui.notify.ui.base
+
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import com.fankes.miui.notify.R
+import com.fankes.miui.notify.hook.HookMedium
+import com.fankes.miui.notify.utils.isNotSystemInDarkMode
+import com.gyf.immersionbar.ktx.immersionBar
+
+abstract class BaseActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ /** 隐藏系统的标题栏 */
+ supportActionBar?.hide()
+ /** 初始化沉浸状态栏 */
+ immersionBar {
+ statusBarColor(R.color.colorThemeBackground)
+ autoDarkModeEnable(true)
+ statusBarDarkFont(isNotSystemInDarkMode)
+ navigationBarColor(R.color.colorThemeBackground)
+ navigationBarDarkIcon(isNotSystemInDarkMode)
+ fitsSystemWindows(true)
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ HookMedium.setWorldReadable(this)
+ }
+
+ override fun onRestart() {
+ super.onRestart()
+ HookMedium.setWorldReadable(this)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ HookMedium.setWorldReadable(this)
+ }
+
+ override fun onBackPressed() {
+ HookMedium.setWorldReadable(this)
+ super.onBackPressed()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/fankes/miui/notify/utils/Utils.kt b/app/src/main/java/com/fankes/miui/notify/utils/Utils.kt
index b06c869..aa43520 100644
--- a/app/src/main/java/com/fankes/miui/notify/utils/Utils.kt
+++ b/app/src/main/java/com/fankes/miui/notify/utils/Utils.kt
@@ -31,7 +31,7 @@ import android.graphics.Bitmap.createBitmap
import android.os.Build
import android.service.notification.StatusBarNotification
import android.util.Base64
-import com.fankes.miui.notify.application.MNvApplication.Companion.appContext
+import com.fankes.miui.notify.application.MNNApplication.Companion.appContext
import java.io.DataInputStream
import java.io.DataOutputStream
@@ -177,6 +177,12 @@ val String.unbase64 get() = Base64.decode(this, Base64.DEFAULT) ?: ByteArray(0)
*/
val ByteArray.bitmap: Bitmap get() = BitmapFactory.decodeByteArray(this, 0, size)
+/**
+ * 字符串解析为位图
+ * @return [Bitmap]
+ */
+val String.bitmap: Bitmap get() = unbase64.bitmap
+
/**
* 圆角图片
* @param radius 圆角度
diff --git a/app/src/main/res/layout/activity_config.xml b/app/src/main/res/layout/activity_config.xml
new file mode 100644
index 0000000..1c901f9
--- /dev/null
+++ b/app/src/main/res/layout/activity_config.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 1f3fb50..3be06b6 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -210,9 +210,9 @@
+
+