From ae1c27aaec898d9eab3d2ffde38f3ed691bec149 Mon Sep 17 00:00:00 2001 From: Fankesyooni Date: Mon, 31 Jan 2022 00:03:11 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=80=9A=E7=9F=A5=E5=9B=BE?= =?UTF-8?q?=E6=A0=87=E4=BC=98=E5=8C=96=E5=90=8D=E5=8D=95=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E5=B9=B6=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81=E5=92=8C=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/misc.xml | 1 + app/src/main/AndroidManifest.xml | 8 +- .../{MNvApplication.kt => MNNApplication.kt} | 9 +- .../fankes/miui/notify/bean/IconDataBean.kt | 38 ++++++++ .../com/fankes/miui/notify/hook/HookMain.kt | 89 +++++++++++++----- .../com/fankes/miui/notify/hook/HookMedium.kt | 79 +++++++++++++++- .../fankes/miui/notify/hook/IconPackParams.kt | 59 ------------ .../miui/notify/params/IconPackParams.kt | 70 ++++++++++++++ .../miui/notify/ui/ConfigureActivity.kt | 36 ++++++++ .../com/fankes/miui/notify/ui/MainActivity.kt | 92 +++---------------- .../miui/notify/ui/base/BaseActivity.kt | 66 +++++++++++++ .../com/fankes/miui/notify/utils/Utils.kt | 8 +- app/src/main/res/layout/activity_config.xml | 42 +++++++++ app/src/main/res/layout/activity_main.xml | 27 +++++- 14 files changed, 449 insertions(+), 175 deletions(-) rename app/src/main/java/com/fankes/miui/notify/application/{MNvApplication.kt => MNNApplication.kt} (86%) create mode 100644 app/src/main/java/com/fankes/miui/notify/bean/IconDataBean.kt delete mode 100644 app/src/main/java/com/fankes/miui/notify/hook/IconPackParams.kt create mode 100644 app/src/main/java/com/fankes/miui/notify/params/IconPackParams.kt create mode 100644 app/src/main/java/com/fankes/miui/notify/ui/ConfigureActivity.kt create mode 100644 app/src/main/java/com/fankes/miui/notify/ui/base/BaseActivity.kt create mode 100644 app/src/main/res/layout/activity_config.xml 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 @@ + +