19 Commits
1.77 ... 1.85

21 changed files with 470 additions and 404 deletions

2
.idea/misc.xml generated
View File

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

View File

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

View File

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

View File

@@ -1,60 +0,0 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
* and/or modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/3/24.
*/
@file:Suppress("MemberVisibilityCanBePrivate")
package com.fankes.coloros.notify.const
import com.fankes.coloros.notify.BuildConfig
/**
* 存储一些静态编译后的值
*/
object Const {
/** 当前模块的包名 */
const val MODULE_PACKAGE_NAME = BuildConfig.APPLICATION_ID
/** 当前模块的版本名称 */
const val MODULE_VERSION_NAME = BuildConfig.VERSION_NAME
/** 当前模块的版本号 */
const val MODULE_VERSION_CODE = BuildConfig.VERSION_CODE
/** 当前模块的版本校验 */
const val MODULE_VERSION_VERIFY = "${MODULE_VERSION_NAME}_${MODULE_VERSION_CODE}_202205091602"
/** 当前模块的版本校验标签 */
const val MODULE_VERSION_VERIFY_TAG = "module_version_verify"
/** 发送通讯广播号标签 - 模块激活状态 */
const val ACTION_MODULE_CHECKING_RECEIVER = "cnn_module_checking_action"
/** 接收通讯广播号标签 - 模块激活状态 */
const val ACTION_MODULE_HANDLER_RECEIVER = "cnn_module_handler_action"
/** 发送通讯广播号标签 - 通知系统界面刷新 */
const val ACTION_REMIND_CHECKING_RECEIVER = "cnn_remind_checking_action"
/** 接收通讯广播号标签 - 通知系统界面刷新 */
const val ACTION_REMIND_HANDLER_RECEIVER = "cnn_remind_handler_action"
}

View File

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

View File

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

View File

@@ -25,10 +25,8 @@
package com.fankes.coloros.notify.hook.entity package com.fankes.coloros.notify.hook.entity
import android.app.WallpaperManager import android.app.WallpaperManager
import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.Color import android.graphics.Color
@@ -37,6 +35,7 @@ import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.graphics.drawable.Icon import android.graphics.drawable.Icon
import android.graphics.drawable.VectorDrawable import android.graphics.drawable.VectorDrawable
import android.os.SystemClock
import android.service.notification.StatusBarNotification import android.service.notification.StatusBarNotification
import android.util.ArrayMap import android.util.ArrayMap
import android.view.View import android.view.View
@@ -46,7 +45,6 @@ import android.widget.ImageView
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import androidx.core.view.children import androidx.core.view.children
import com.fankes.coloros.notify.bean.IconDataBean import com.fankes.coloros.notify.bean.IconDataBean
import com.fankes.coloros.notify.const.Const
import com.fankes.coloros.notify.data.DataConst import com.fankes.coloros.notify.data.DataConst
import com.fankes.coloros.notify.hook.HookConst.ANDROID_PACKAGE_NAME import com.fankes.coloros.notify.hook.HookConst.ANDROID_PACKAGE_NAME
import com.fankes.coloros.notify.hook.HookConst.SYSTEMUI_PACKAGE_NAME import com.fankes.coloros.notify.hook.HookConst.SYSTEMUI_PACKAGE_NAME
@@ -56,6 +54,7 @@ import com.fankes.coloros.notify.param.IconPackParams
import com.fankes.coloros.notify.utils.drawable.drawabletoolbox.DrawableBuilder import com.fankes.coloros.notify.utils.drawable.drawabletoolbox.DrawableBuilder
import com.fankes.coloros.notify.utils.factory.* import com.fankes.coloros.notify.utils.factory.*
import com.fankes.coloros.notify.utils.tool.IconAdaptationTool import com.fankes.coloros.notify.utils.tool.IconAdaptationTool
import com.fankes.coloros.notify.utils.tool.SystemUITool
import com.highcapable.yukihookapi.hook.bean.VariousClass import com.highcapable.yukihookapi.hook.bean.VariousClass
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
import com.highcapable.yukihookapi.hook.factory.current import com.highcapable.yukihookapi.hook.factory.current
@@ -216,65 +215,6 @@ object SystemUIHooker : YukiBaseHooker() {
/** 是否已经使用过缓存刷新功能 */ /** 是否已经使用过缓存刷新功能 */
private var isUsingCachingMethod = false private var isUsingCachingMethod = false
/** 是否已经注册广播 */
private var isRegisterReceiver = false
/** 用户解锁屏幕广播接收器 */
private val userPresentReceiver by lazy {
object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
/** 解锁后重新刷新状态栏图标防止系统重新设置它 */
if (isUsingCachingMethod) refreshStatusBarIcons()
}
}
}
/** 模块广播接收器 */
private val moduleCheckingReceiver by lazy {
object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
context?.sendBroadcast(Intent().apply {
action = Const.ACTION_MODULE_HANDLER_RECEIVER
putExtra("isRegular", true)
putExtra("isValied", intent?.isValiedModule)
})
}
}
}
/** 通知广播接收器 */
private val remindCheckingReceiver by lazy {
object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) = delayedRun(ms = 300) {
if (intent?.isValiedModule == true)
recachingPrefs(intent.getBooleanExtra("isRefreshCacheOnly", false))
context?.sendBroadcast(Intent().apply {
action = Const.ACTION_REMIND_HANDLER_RECEIVER
putExtra("isGrasp", true)
putExtra("isValied", intent?.isValiedModule)
})
}
}
}
/**
* 判断模块和宿主版本是否一致
* @return [Boolean]
*/
private val Intent.isValiedModule get() = getStringExtra(Const.MODULE_VERSION_VERIFY_TAG) == Const.MODULE_VERSION_VERIFY
/**
* 注册广播接收器
* @param context 实例
*/
private fun registerReceiver(context: Context) {
if (isRegisterReceiver) return
context.registerReceiver(userPresentReceiver, IntentFilter().apply { addAction(Intent.ACTION_USER_PRESENT) })
context.registerReceiver(moduleCheckingReceiver, IntentFilter().apply { addAction(Const.ACTION_MODULE_CHECKING_RECEIVER) })
context.registerReceiver(remindCheckingReceiver, IntentFilter().apply { addAction(Const.ACTION_REMIND_CHECKING_RECEIVER) })
isRegisterReceiver = true
}
/** /**
* 是否启用通知图标优化功能 * 是否启用通知图标优化功能
* @param isHooking 是否判断启用通知功能 - 默认:是 * @param isHooking 是否判断启用通知功能 - 默认:是
@@ -488,6 +428,13 @@ object SystemUIHooker : YukiBaseHooker() {
) = runInSafe { ) = runInSafe {
compatCustomIcon(isGrayscaleIcon, packageName).also { customPair -> compatCustomIcon(isGrayscaleIcon, packageName).also { customPair ->
when { when {
prefs.get(DataConst.ENABLE_NOTIFY_ICON_FORCE_APP_ICON) && isEnableHookColorNotifyIcon(isHooking = false) ->
iconView.apply {
/** 重新设置图标 */
setImageDrawable(appIcons[packageName] ?: context.findAppIcon(packageName))
/** 设置默认样式 */
setDefaultNotifyIconViewStyle()
}
customPair.first != null || isGrayscaleIcon -> iconView.apply { customPair.first != null || isGrayscaleIcon -> iconView.apply {
/** 设置不要裁切到边界 */ /** 设置不要裁切到边界 */
clipToOutline = false clipToOutline = false
@@ -515,7 +462,12 @@ object SystemUIHooker : YukiBaseHooker() {
/** 判断风格并开始 Hook */ /** 判断风格并开始 Hook */
if (isA12Style) { if (isA12Style) {
background = DrawableBuilder().rounded().solidColor(newApplyColor).build() /** 通知图标边框圆角大小 */
background = DrawableBuilder()
.rectangle()
.cornerRadius(prefs.get(DataConst.NOTIFY_ICON_CORNER).dp(context))
.solidColor(newApplyColor)
.build()
setColorFilter(newStyle) setColorFilter(newStyle)
setPadding(2.dp(context), 2.dp(context), 2.dp(context), 2.dp(context)) setPadding(2.dp(context), 2.dp(context), 2.dp(context), 2.dp(context))
} else { } else {
@@ -527,23 +479,8 @@ object SystemUIHooker : YukiBaseHooker() {
else -> iconView.apply { else -> iconView.apply {
/** 重新设置图标 */ /** 重新设置图标 */
setImageDrawable(nf.compatPushingIcon(drawable)) setImageDrawable(nf.compatPushingIcon(drawable))
/** 设置裁切到边界 */ /** 设置默认样式 */
clipToOutline = true setDefaultNotifyIconViewStyle()
/** 设置一个圆角轮廓裁切 */
outlineProvider = object : ViewOutlineProvider() {
override fun getOutline(view: View, out: Outline) {
out.setRoundRect(
0, 0,
view.width, view.height, 3.dpFloat(context)
)
}
}
/** 清除图标间距 */
setPadding(0, 0, 0, 0)
/** 清除背景 */
background = null
/** 清除着色 */
colorFilter = null
} }
} }
/** 打印日志 */ /** 打印日志 */
@@ -580,6 +517,35 @@ object SystemUIHooker : YukiBaseHooker() {
} }
} }
/** 设置默认通知栏通知图标样式 */
private fun ImageView.setDefaultNotifyIconViewStyle() {
/** 设置裁切到边界 */
clipToOutline = true
/** 设置一个圆角轮廓裁切 */
outlineProvider = object : ViewOutlineProvider() {
override fun getOutline(view: View, out: Outline) {
out.setRoundRect(
0, 0,
view.width, view.height, 3.dpFloat(context)
)
}
}
/** 清除图标间距 */
setPadding(0, 0, 0, 0)
/** 清除背景 */
background = null
/** 清除着色 */
colorFilter = null
}
/** 注册 */
private fun register() {
/** 解锁后重新刷新状态栏图标防止系统重新设置它 */
onAppLifecycle { registerReceiver(Intent.ACTION_USER_PRESENT) { _, _ -> if (isUsingCachingMethod) refreshStatusBarIcons() } }
/** 刷新图标缓存 */
SystemUITool.Host.onRefreshSystemUI(param = this) { recachingPrefs(it) }
}
/** 缓存图标数据 */ /** 缓存图标数据 */
private fun cachingIconDatas() { private fun cachingIconDatas() {
iconDatas.clear() iconDatas.clear()
@@ -594,17 +560,25 @@ object SystemUIHooker : YukiBaseHooker() {
/** /**
* 刷新缓存数据 * 刷新缓存数据
* @param isRefreshCacheOnly 仅刷新缓存不刷新图标和通知改变 - 默认:否 * @param isRefreshCacheOnly 仅刷新缓存不刷新图标和通知改变 - 默认:否
* @return [Boolean] 是否成功
*/ */
private fun recachingPrefs(isRefreshCacheOnly: Boolean = false) { private fun recachingPrefs(isRefreshCacheOnly: Boolean = false): Boolean {
isUsingCachingMethod = true /** 必要的延迟防止 Sp 存储不刷新 */
prefs.clearCache() SystemClock.sleep(100)
cachingIconDatas() /** 获取可读写状态 */
if (isRefreshCacheOnly) return return prefs.isXSharePrefsReadable.also {
refreshStatusBarIcons() isUsingCachingMethod = true
refreshNotificationIcons() prefs.clearCache()
cachingIconDatas()
if (isRefreshCacheOnly) return@also
refreshStatusBarIcons()
refreshNotificationIcons()
}
} }
override fun onHook() { override fun onHook() {
/** 注册 */
register()
/** 缓存图标数据 */ /** 缓存图标数据 */
cachingIconDatas() cachingIconDatas()
/** 移除开发者警告通知 */ /** 移除开发者警告通知 */
@@ -697,12 +671,8 @@ object SystemUIHooker : YukiBaseHooker() {
param(StatusBarNotificationClass) param(StatusBarNotificationClass)
} }
afterHook { afterHook {
if (args().first().any() != null) instance<ImageView>().also { /** 注册壁纸颜色监听 */
/** 注册壁纸颜色监听 */ if (args().first().any() != null) instance<ImageView>().also { registerWallpaperColorChanged(it) }
registerWallpaperColorChanged(it)
/** 注册广播 */
registerReceiver(it.context)
}
} }
} }
} }
@@ -902,8 +872,6 @@ object SystemUIHooker : YukiBaseHooker() {
} }
afterHook { afterHook {
args().first().cast<Context>()?.also { args().first().cast<Context>()?.also {
/** 注册广播 */
registerReceiver(it)
/** 注册定时监听 */ /** 注册定时监听 */
if (isEnableHookColorNotifyIcon() && prefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_AUTO)) if (isEnableHookColorNotifyIcon() && prefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_AUTO))
IconAdaptationTool.prepareAutoUpdateIconRule( IconAdaptationTool.prepareAutoUpdateIconRule(

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -370,27 +370,23 @@ fun toast(msg: String) = Toast.makeText(appContext, msg, Toast.LENGTH_SHORT).sho
* *
* [T] 为指定的 [Activity] * [T] 为指定的 [Activity]
*/ */
inline fun <reified T : Activity> Context.navigate() = runInSafe { startActivity(Intent(this, T::class.java)) } inline fun <reified T : Activity> Context.navigate() = runInSafe {
startActivity(Intent(if (this is Service) applicationContext else this, T::class.java).apply {
/** if (this@navigate !is Activity) flags = Intent.FLAG_ACTIVITY_NEW_TASK
* 跳转到指定页面 })
* }
* [T] 为指定的 [Activity]
*/
inline fun <reified T : Activity> Service.navigate() =
runInSafe { startActivity(Intent(this, T::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK }) }
/** /**
* 弹出 [Snackbar] * 弹出 [Snackbar]
* @param msg 提示内容 * @param msg 提示内容
* @param actionText 按钮文本 - 不写默认取消按钮 * @param actionText 按钮文本 - 不写默认取消按钮
* @param it 按钮事件回调 * @param callback 按钮事件回调
*/ */
fun Context.snake(msg: String, actionText: String = "", it: () -> Unit = {}) = fun Context.snake(msg: String, actionText: String = "", callback: () -> Unit = {}) =
Snackbar.make((this as Activity).findViewById(android.R.id.content), msg, Snackbar.LENGTH_LONG).apply { Snackbar.make((this as Activity).findViewById(android.R.id.content), msg, Snackbar.LENGTH_LONG).apply {
if (actionText.isBlank()) return@apply if (actionText.isBlank()) return@apply
setActionTextColor(if (isSystemInDarkMode) Color.BLACK else Color.WHITE) setActionTextColor(if (isSystemInDarkMode) Color.BLACK else Color.WHITE)
setAction(actionText) { it() } setAction(actionText) { callback() }
}.show() }.show()
/** /**

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,59 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
* and/or modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/5/30.
*/
package com.fankes.coloros.notify.utils.tool
import android.content.Context
import com.fankes.coloros.notify.utils.factory.openBrowser
import com.fankes.coloros.notify.utils.factory.showDialog
import com.highcapable.yukihookapi.YukiHookAPI
import com.highcapable.yukihookapi.hook.factory.modulePrefs
import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData
/**
* [YukiHookAPI] 的自动推广工具类
*/
object YukiPromoteTool {
/** 推广已读存储键值 */
private val YUKI_PROMOTE_READED = PrefsData("yuki_promote_readed", false)
/**
* 显示推广对话框
* @param context 实例
*/
fun promote(context: Context) {
fun saveReaded() = context.modulePrefs.put(YUKI_PROMOTE_READED, value = true)
if (context.modulePrefs.get(YUKI_PROMOTE_READED).not())
context.showDialog {
title = "面向开发者的推广"
msg = "你想快速拥有一个自己的 Xposed 模块吗,你只需要拥有基础的 Android 开发经验以及使用 Kotlin 编程语言即可。\n\n" +
"快来体验 YukiHookAPI这是一个使用 Kotlin 重新构建的高效 Xposed Hook API助你的开发变得更轻松。"
confirmButton(text = "去看看") {
context.openBrowser(url = "https://github.com/fankes/YukiHookAPI")
saveReaded()
}
cancelButton(text = "我不是开发者") { saveReaded() }
noCancelable()
}
}
}

View File

@@ -563,15 +563,13 @@
android:elevation="0dp" android:elevation="0dp"
android:gravity="center" android:gravity="center"
android:orientation="vertical" android:orientation="vertical"
android:paddingLeft="10dp" android:paddingTop="15dp">
android:paddingTop="15dp"
android:paddingRight="10dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="5dp" android:layout_marginLeft="15dp"
android:layout_marginRight="5dp" android:layout_marginRight="15dp"
android:gravity="center|start"> android:gravity="center|start">
<ImageView <ImageView
@@ -594,8 +592,8 @@
android:id="@+id/notify_icon_fix_switch" android:id="@+id/notify_icon_fix_switch"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="5dp" android:layout_marginLeft="15dp"
android:layout_marginRight="5dp" android:layout_marginRight="15dp"
android:text="启用通知图标优化" android:text="启用通知图标优化"
android:textColor="@color/colorTextGray" android:textColor="@color/colorTextGray"
android:textSize="15sp" /> android:textSize="15sp" />
@@ -604,8 +602,8 @@
android:id="@+id/notify_icon_fix_button" android:id="@+id/notify_icon_fix_button"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="3dp" android:layout_marginLeft="13dp"
android:layout_marginRight="3dp" android:layout_marginRight="13dp"
android:layout_marginBottom="10dp" android:layout_marginBottom="10dp"
android:background="@drawable/bg_button_round" android:background="@drawable/bg_button_round"
android:gravity="center" android:gravity="center"
@@ -618,8 +616,8 @@
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="5dp" android:layout_marginLeft="15dp"
android:layout_marginRight="5dp" android:layout_marginRight="15dp"
android:layout_marginBottom="10dp" android:layout_marginBottom="10dp"
android:alpha="0.6" android:alpha="0.6"
android:lineSpacingExtra="6dp" android:lineSpacingExtra="6dp"
@@ -630,8 +628,8 @@
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="5dp" android:layout_marginLeft="15dp"
android:layout_marginRight="5dp" android:layout_marginRight="15dp"
android:layout_marginBottom="10dp" android:layout_marginBottom="10dp"
android:alpha="0.6" android:alpha="0.6"
android:lineSpacingExtra="6dp" android:lineSpacingExtra="6dp"
@@ -639,12 +637,119 @@
android:textColor="@color/colorTextDark" android:textColor="@color/colorTextDark"
android:textSize="12sp" /> android:textSize="12sp" />
<LinearLayout
android:id="@+id/notify_icon_custom_corner_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginBottom="5dp"
android:gravity="center|start"
android:text="调整通知栏中的图标边框圆角大小"
android:textAllCaps="false"
android:textColor="@color/colorTextGray"
android:textSize="15sp" />
<androidx.appcompat.widget.AppCompatSeekBar
android:id="@+id/notify_icon_custom_corner_seekbar"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="5dp"
android:max="10"
android:min="0"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:progress="10" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:gravity="center"
android:orientation="horizontal"
android:paddingTop="5dp"
android:paddingBottom="15dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:alpha="0.75"
android:ellipsize="end"
android:gravity="center"
android:maxWidth="100dp"
android:singleLine="true"
android:text="当前"
android:textColor="@color/colorTextGray"
android:textSize="13.5sp" />
<TextView
android:id="@+id/notify_icon_custom_corner_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="center"
android:maxWidth="100dp"
android:singleLine="true"
android:text="10 dp"
android:textColor="@color/colorTextGray"
android:textSize="15sp"
android:textStyle="bold" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:alpha="0.6"
android:lineSpacingExtra="6dp"
android:text="你可以拖拽滑动条来调整通知栏中图标的边框圆角大小,仅支持启用了 Android 12 通知栏风格的通知图标。"
android:textColor="@color/colorTextDark"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/notify_icon_force_app_icon_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:orientation="vertical">
<com.fankes.coloros.notify.ui.view.MaterialSwitch
android:id="@+id/notify_icon_force_app_icon_switch"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_marginBottom="5dp"
android:text="通知栏中的图标强制为 APP 图标"
android:textColor="@color/colorTextGray"
android:textSize="15sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:alpha="0.6"
android:lineSpacingExtra="6dp"
android:text="此选项默认关闭,开启后下拉通知栏中的通知图标将会被替换为 APP 自身图标,但是不会更改状态栏中的通知图标,这是一个破坏原生通知图标的行为,仅针对部分有需要的用户而添加,我们不推荐开启这个功能,请根据个人偏好进行选择是否需要开启。"
android:textColor="@color/colorTextDark"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/notify_icon_fix_notify_item" android:id="@+id/notify_icon_fix_notify_item"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="5dp" android:layout_marginLeft="15dp"
android:layout_marginRight="5dp" android:layout_marginRight="15dp"
android:orientation="vertical"> android:orientation="vertical">
<com.fankes.coloros.notify.ui.view.MaterialSwitch <com.fankes.coloros.notify.ui.view.MaterialSwitch
@@ -671,8 +776,8 @@
android:id="@+id/notify_icon_auto_sync_item" android:id="@+id/notify_icon_auto_sync_item"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="5dp" android:layout_marginLeft="15dp"
android:layout_marginRight="5dp" android:layout_marginRight="15dp"
android:animateLayoutChanges="true" android:animateLayoutChanges="true"
android:orientation="vertical"> android:orientation="vertical">

View File

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

View File

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