mirror of
https://github.com/fankes/MIUINativeNotifyIcon.git
synced 2025-09-04 01:35:26 +08:00
Modify merge YukiHookAPI new usage and compatible with API 33
This commit is contained in:
@@ -39,7 +39,7 @@ import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit
|
||||
class HookEntry : IYukiHookXposedInit {
|
||||
|
||||
override fun onInit() = configs {
|
||||
debugTag = "MIUINativeNotifyIcon"
|
||||
debugLog { tag = "MIUINativeNotifyIcon" }
|
||||
isDebug = false
|
||||
}
|
||||
|
||||
|
@@ -179,7 +179,7 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
*/
|
||||
private fun isGrayscaleIcon(context: Context, drawable: Drawable) =
|
||||
if (prefs.get(DataConst.ENABLE_COLOR_ICON_COMPAT).not()) safeOfFalse {
|
||||
ContrastColorUtilClass.clazz.let {
|
||||
ContrastColorUtilClass.toClass().let {
|
||||
it.method {
|
||||
name = "isGrayscaleIcon"
|
||||
param(DrawableClass)
|
||||
@@ -197,7 +197,7 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
* @return [Boolean]
|
||||
*/
|
||||
private val hasHandleHeaderViews
|
||||
get() = safeOfFalse { NotificationHeaderViewWrapperClass.clazz.hasMethod { name = "handleHeaderViews" } }
|
||||
get() = NotificationHeaderViewWrapperClass.toClassOrNull()?.hasMethod { name = "handleHeaderViews" } ?: false
|
||||
|
||||
/**
|
||||
* 处理为圆角图标
|
||||
@@ -217,7 +217,7 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
private fun StatusBarNotification.compatPushingIcon(context: Context, iconDrawable: Drawable) = safeOf(iconDrawable) {
|
||||
/** 给 MIPUSH 设置 APP 自己的图标 */
|
||||
if (isXmsf && nfPkgName.isNotBlank())
|
||||
context.findAppIcon(xmsfPkgName) ?: iconDrawable
|
||||
context.appIconOf(xmsfPkgName) ?: iconDrawable
|
||||
else iconDrawable
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
isGrayscale: Boolean
|
||||
) {
|
||||
if (prefs.get(DataConst.ENABLE_MODULE_LOG)) loggerD(
|
||||
msg = "$tag --> [${context.findAppName(name = expandedNf?.nfPkgName ?: "")}][${expandedNf?.nfPkgName}] " +
|
||||
msg = "$tag --> [${context.appNameOf(packageName = expandedNf?.nfPkgName ?: "")}][${expandedNf?.nfPkgName}] " +
|
||||
"custom [$isCustom] " +
|
||||
"grayscale [$isGrayscale] " +
|
||||
"xmsf [${expandedNf?.isXmsf}]"
|
||||
@@ -282,22 +282,21 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
* 是否为 MIUI 样式通知栏 - 旧版 - 新版一律返回 false
|
||||
* @return [Boolean]
|
||||
*/
|
||||
private val isShowMiuiStyle get() = NotificationUtilClass.clazz.method { name = "showMiuiStyle" }.ignoredError().get().boolean()
|
||||
private val isShowMiuiStyle
|
||||
get() = NotificationUtilClass.toClassOrNull()?.method { name = "showMiuiStyle" }?.ignored()?.get()?.boolean() ?: false
|
||||
|
||||
/**
|
||||
* 是否没有单独的 MIUI 通知栏样式
|
||||
* @return [Boolean]
|
||||
*/
|
||||
private val isNotHasAbsoluteMiuiStyle get() = MiuiNotificationViewWrapperClass.hasClass.not()
|
||||
private val isNotHasAbsoluteMiuiStyle get() = MiuiNotificationViewWrapperClass.hasClass().not()
|
||||
|
||||
/**
|
||||
* 获取全局上下文
|
||||
* @return [Context] or null
|
||||
*/
|
||||
private val globalContext
|
||||
get() = safeOfNull {
|
||||
SystemUIApplicationClass.clazz.method { name = "getContext" }.ignoredError().get().invoke<Context?>() ?: appContext
|
||||
}
|
||||
get() = SystemUIApplicationClass.toClassOrNull()?.method { name = "getContext" }?.ignored()?.get()?.invoke<Context?>() ?: appContext
|
||||
|
||||
/**
|
||||
* 注册主题壁纸改变颜色监听
|
||||
@@ -314,7 +313,7 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
|
||||
/** 刷新状态栏小图标 */
|
||||
private fun refreshStatusBarIcons() = runInSafe {
|
||||
StatusBarIconViewClass.clazz.field { name = "mNotification" }.also { result ->
|
||||
StatusBarIconViewClass.toClassOrNull()?.field { name = "mNotification" }?.also { result ->
|
||||
notificationIconContainer?.children?.forEach {
|
||||
/** 得到通知实例 */
|
||||
val nf = result.get(it).cast<StatusBarNotification>() ?: return
|
||||
@@ -328,12 +327,10 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
|
||||
/** 刷新通知小图标 */
|
||||
private fun refreshNotificationIcons() = runInSafe {
|
||||
notificationPresenter?.current {
|
||||
method {
|
||||
name = "updateNotificationsOnDensityOrFontScaleChanged"
|
||||
emptyParam()
|
||||
}.call()
|
||||
}
|
||||
notificationPresenter?.current()?.method {
|
||||
name = "updateNotificationsOnDensityOrFontScaleChanged"
|
||||
emptyParam()
|
||||
}?.call()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -460,6 +457,7 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
|
||||
/** 获取通知小图标 */
|
||||
val iconDrawable = notifyInstance.notification.smallIcon.loadDrawable(context)
|
||||
?: return@let loggerW(msg = "compatNotifyIcon got null smallIcon")
|
||||
|
||||
/** 判断图标风格 */
|
||||
val isGrayscaleIcon = notifyInstance.isXmsf.not() && isGrayscaleIcon(context, iconDrawable)
|
||||
@@ -479,7 +477,7 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
/** 处理自定义通知图标优化 */
|
||||
when {
|
||||
prefs.get(DataConst.ENABLE_NOTIFY_ICON_FORCE_APP_ICON) && isEnableHookColorNotifyIcon(isHooking = false) ->
|
||||
setDefaultNotifyIcon(context.findAppIcon(notifyInstance.nfPkgName))
|
||||
setDefaultNotifyIcon(context.appIconOf(notifyInstance.nfPkgName))
|
||||
customIcon != null -> iconImageView.apply {
|
||||
/** 设置不要裁切到边界 */
|
||||
clipToOutline = false
|
||||
@@ -492,7 +490,7 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
background = DrawableBuilder()
|
||||
.rectangle()
|
||||
.cornerRadius(iconCorner.dp(context))
|
||||
.solidColor(if (context.isSystemInDarkMode) customIconColor.brighter else customIconColor)
|
||||
.solidColor(if (context.isSystemInDarkMode) customIconColor.brighterColor else customIconColor)
|
||||
.build()
|
||||
/** 设置原生的背景边距 */
|
||||
if (isUseAndroid12Style) setPadding(4.dp(context), 4.dp(context), 4.dp(context), 4.dp(context))
|
||||
@@ -512,7 +510,7 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
background = DrawableBuilder()
|
||||
.rectangle()
|
||||
.cornerRadius(iconCorner.dp(context))
|
||||
.solidColor(if (context.isSystemInDarkMode) it.brighter else it)
|
||||
.solidColor(if (context.isSystemInDarkMode) it.brighterColor else it)
|
||||
.build()
|
||||
}
|
||||
/** 设置原生的背景边距 */
|
||||
@@ -536,6 +534,7 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
expandedNf?.let { notifyInstance ->
|
||||
/** 获取通知小图标 */
|
||||
val iconDrawable = notifyInstance.notification.smallIcon.loadDrawable(context)
|
||||
?: return loggerW(msg = "hasIgnoreStatusBarIconColor got null smallIcon").let { true }
|
||||
|
||||
/** 判断是否不是灰度图标 */
|
||||
val isNotGrayscaleIcon = notifyInstance.isXmsf || isGrayscaleIcon(context, iconDrawable).not()
|
||||
@@ -564,13 +563,13 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
* 从父类中得到 mRow 变量 - [ExpandableNotificationRowClass]
|
||||
* 获取其中的得到通知方法
|
||||
*/
|
||||
val row = NotificationViewWrapperClass.clazz.field {
|
||||
val row = NotificationViewWrapperClass.toClassOrNull()?.field {
|
||||
name = "mRow"
|
||||
}.get(this).self?.also {
|
||||
isExpanded = ExpandableNotificationRowClass.clazz.method {
|
||||
}?.get(this)?.any()?.also {
|
||||
isExpanded = ExpandableNotificationRowClass.toClassOrNull()?.method {
|
||||
name = "isExpanded"
|
||||
returnType = BooleanType
|
||||
}.get(it).boolean()
|
||||
}?.get(it)?.boolean() ?: false
|
||||
}
|
||||
return Pair(isExpanded, row)
|
||||
}
|
||||
@@ -580,15 +579,15 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
* @return [StatusBarNotification] or null
|
||||
*/
|
||||
private fun Any?.getSbn() =
|
||||
ExpandableNotificationRowClass.clazz
|
||||
.method { name = "getEntry" }
|
||||
.get(this).call()?.let {
|
||||
ExpandableNotificationRowClass.toClassOrNull()
|
||||
?.method { name = "getEntry" }
|
||||
?.get(this)?.call()?.let {
|
||||
it.javaClass.method {
|
||||
name = "getSbn"
|
||||
}.ignoredError().get(it).invoke<StatusBarNotification>()
|
||||
} ?: ExpandableNotificationRowClass.clazz
|
||||
.method { name = "getStatusBarNotification" }
|
||||
.get(this).invoke<StatusBarNotification>()
|
||||
}.ignored().get(it).invoke<StatusBarNotification>()
|
||||
} ?: ExpandableNotificationRowClass.toClassOrNull()
|
||||
?.method { name = "getStatusBarNotification" }
|
||||
?.get(this)?.invoke<StatusBarNotification>()
|
||||
|
||||
/**
|
||||
* 根据当前 [ImageView] 的父布局克隆一个新的 [ImageView]
|
||||
@@ -614,8 +613,8 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
} ?: initiate(this)
|
||||
}
|
||||
|
||||
/** 注册 */
|
||||
private fun register() {
|
||||
/** 注册生命周期 */
|
||||
private fun registerLifecycle() {
|
||||
/** 解锁后重新刷新状态栏图标防止系统重新设置它 */
|
||||
onAppLifecycle { registerReceiver(Intent.ACTION_USER_PRESENT) { _, _ -> if (isUsingCachingMethod) refreshStatusBarIcons() } }
|
||||
/** 刷新图标缓存 */
|
||||
@@ -653,8 +652,8 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
}
|
||||
|
||||
override fun onHook() {
|
||||
/** 注册 */
|
||||
register()
|
||||
/** 注册生命周期 */
|
||||
registerLifecycle()
|
||||
/** 缓存图标数据 */
|
||||
cachingIconDatas()
|
||||
/** 注入 MIUI 自己增加的一个工具类 */
|
||||
@@ -714,8 +713,8 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
* MIUI 12 进行单独判断
|
||||
*/
|
||||
field { name = "mCurrentSetColor" }.get(instance).int().also { color ->
|
||||
alpha = if (color.isWhite) 0.95f else 0.8f
|
||||
setColorFilter(if (color.isWhite) color else Color.BLACK)
|
||||
alpha = if (color.isWhiteColor) 0.95f else 0.8f
|
||||
setColorFilter(if (color.isWhiteColor) color else Color.BLACK)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -741,7 +740,7 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
/** 注入通知控制器实例 */
|
||||
StatusBarNotificationPresenterClass.hook {
|
||||
injectMember {
|
||||
allConstructors()
|
||||
allMembers(MembersType.CONSTRUCTOR)
|
||||
afterHook { notificationPresenter = instance }
|
||||
}
|
||||
}
|
||||
@@ -768,7 +767,7 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
.get(instance).set(prefs.get(DataConst.HOOK_STATUS_ICON_COUNT)
|
||||
.let { if (it in 0..100) it else 5 })
|
||||
}
|
||||
}.by { NotificationIconContainerClass.clazz.hasField { name = "MAX_STATIC_ICONS" } }
|
||||
}.by { NotificationIconContainerClass.toClassOrNull()?.hasField { name = "MAX_STATIC_ICONS" } ?: false }
|
||||
/** 旧版方法 - 新版不存在 */
|
||||
injectMember {
|
||||
method {
|
||||
@@ -798,9 +797,8 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
if (isNotHasAbsoluteMiuiStyle && isShowMiuiStyle) return@afterHook
|
||||
|
||||
/** 获取小图标 */
|
||||
val iconImageView =
|
||||
NotificationHeaderViewWrapperClass.clazz
|
||||
.field { name = "mIcon" }.get(instance).cast<ImageView>() ?: return@afterHook
|
||||
val iconImageView = NotificationHeaderViewWrapperClass.toClassOrNull()
|
||||
?.field { name = "mIcon" }?.get(instance)?.cast<ImageView>() ?: return@afterHook
|
||||
|
||||
/** 获取 [ExpandableNotificationRowClass] */
|
||||
val rowPair = instance.getRowPair()
|
||||
@@ -848,11 +846,10 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
param(BooleanType)
|
||||
}
|
||||
afterHook {
|
||||
val expandedNf = NotificationChildrenContainerClass.clazz.field {
|
||||
name = "mContainingNotification"
|
||||
}.get(instance).self.getSbn()
|
||||
field { name = "mAppIcon" }.get(instance).cast<ImageView>()?.apply {
|
||||
compatNotifyIcon(context, expandedNf, iconImageView = this, isUseAndroid12Style = true)
|
||||
compatNotifyIcon(context, NotificationChildrenContainerClass.toClassOrNull()?.field {
|
||||
name = "mContainingNotification"
|
||||
}?.get(instance)?.any()?.getSbn(), iconImageView = this, isUseAndroid12Style = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -892,18 +889,16 @@ object SystemUIHooker : YukiBaseHooker() {
|
||||
it.getBooleanExtra(Intent.EXTRA_REPLACING, false)
|
||||
) return@also
|
||||
when (it.action) {
|
||||
Intent.ACTION_PACKAGE_ADDED ->
|
||||
it.data?.schemeSpecificPart?.also { newPkgName ->
|
||||
if (iconDatas.takeIf { e -> e.isNotEmpty() }
|
||||
?.filter { e -> e.packageName == newPkgName }
|
||||
.isNullOrEmpty()
|
||||
) IconAdaptationTool.pushNewAppSupportNotify(args().first().cast()!!, newPkgName)
|
||||
}
|
||||
Intent.ACTION_PACKAGE_REMOVED ->
|
||||
IconAdaptationTool.removeNewAppSupportNotify(
|
||||
context = args().first().cast()!!,
|
||||
packageName = it.data?.schemeSpecificPart ?: ""
|
||||
)
|
||||
Intent.ACTION_PACKAGE_ADDED -> it.data?.schemeSpecificPart?.also { newPkgName ->
|
||||
if (iconDatas.takeIf { e -> e.isNotEmpty() }
|
||||
?.filter { e -> e.packageName == newPkgName }
|
||||
.isNullOrEmpty()
|
||||
) IconAdaptationTool.pushNewAppSupportNotify(args().first().cast()!!, newPkgName)
|
||||
}
|
||||
Intent.ACTION_PACKAGE_REMOVED -> IconAdaptationTool.removeNewAppSupportNotify(
|
||||
context = args().first().cast()!!,
|
||||
packageName = it.data?.schemeSpecificPart ?: ""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -20,7 +20,7 @@
|
||||
*
|
||||
* This file is Created by fankes on 2022/1/30.
|
||||
*/
|
||||
@file:Suppress("SetTextI18n", "InflateParams", "DEPRECATION")
|
||||
@file:Suppress("SetTextI18n", "InflateParams")
|
||||
|
||||
package com.fankes.miui.notify.ui.activity
|
||||
|
||||
@@ -67,7 +67,7 @@ class ConfigureActivity : BaseActivity<ActivityConfigBinding>() {
|
||||
return
|
||||
}
|
||||
/** 返回按钮点击事件 */
|
||||
binding.titleBackIcon.setOnClickListener { onBackPressed() }
|
||||
binding.titleBackIcon.setOnClickListener { callOnBackPressed() }
|
||||
/** 刷新适配器结果相关 */
|
||||
refreshAdapterResult()
|
||||
/** 设置上下按钮点击事件 */
|
||||
@@ -117,7 +117,7 @@ class ConfigureActivity : BaseActivity<ActivityConfigBinding>() {
|
||||
onBindViews<AdapterConfigBinding> { binding, position ->
|
||||
iconDatas[position].also { bean ->
|
||||
binding.adpAppIcon.setImageBitmap(bean.iconBitmap)
|
||||
(if (bean.iconColor != 0) bean.iconColor else resources.getColor(R.color.colorTextGray)).also { color ->
|
||||
(if (bean.iconColor != 0) bean.iconColor else resources.colorOf(R.color.colorTextGray)).also { color ->
|
||||
binding.adpAppIcon.setColorFilter(color)
|
||||
binding.adpAppName.setTextColor(color)
|
||||
}
|
||||
@@ -203,6 +203,20 @@ class ConfigureActivity : BaseActivity<ActivityConfigBinding>() {
|
||||
removeExtra("isNewAppSupport")
|
||||
removeExtra("isShowUpdDialog")
|
||||
}
|
||||
/** 设置返回监听事件 */
|
||||
addOnBackPressedEvent {
|
||||
if (MainActivity.isActivityLive.not())
|
||||
showDialog {
|
||||
title = "提示"
|
||||
msg = "要返回模块主页吗?"
|
||||
confirmButton {
|
||||
releaseEventAndBack()
|
||||
navigate<MainActivity>()
|
||||
}
|
||||
cancelButton { releaseEventAndBack() }
|
||||
}
|
||||
else releaseEventAndBack()
|
||||
}
|
||||
}
|
||||
|
||||
/** 开始手动同步 */
|
||||
@@ -239,18 +253,4 @@ class ConfigureActivity : BaseActivity<ActivityConfigBinding>() {
|
||||
else iconAllDatas.filter {
|
||||
it.appName.lowercase().contains(filterText.lowercase()) || it.packageName.lowercase().contains(filterText.lowercase())
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (MainActivity.isActivityLive.not())
|
||||
showDialog {
|
||||
title = "提示"
|
||||
msg = "要返回模块主页吗?"
|
||||
confirmButton {
|
||||
super.onBackPressed()
|
||||
navigate<MainActivity>()
|
||||
}
|
||||
cancelButton { super.onBackPressed() }
|
||||
}
|
||||
else super.onBackPressed()
|
||||
}
|
||||
}
|
@@ -31,9 +31,9 @@ import androidx.core.view.WindowCompat
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.fankes.miui.notify.R
|
||||
import com.fankes.miui.notify.utils.factory.isNotSystemInDarkMode
|
||||
import com.highcapable.yukihookapi.hook.factory.current
|
||||
import com.highcapable.yukihookapi.hook.factory.method
|
||||
import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass
|
||||
import java.lang.reflect.ParameterizedType
|
||||
|
||||
abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
|
||||
|
||||
@@ -49,15 +49,11 @@ abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
isMainThreadRunning = true
|
||||
javaClass.genericSuperclass.also { type ->
|
||||
if (type is ParameterizedType) {
|
||||
binding = (type.actualTypeArguments[0] as Class<VB>).method {
|
||||
name = "inflate"
|
||||
param(LayoutInflaterClass)
|
||||
}.get().invoke<VB>(layoutInflater) ?: error("binding failed")
|
||||
setContentView(binding.root)
|
||||
} else error("binding but got wrong type")
|
||||
}
|
||||
binding = current().generic()?.argument()?.method {
|
||||
name = "inflate"
|
||||
param(LayoutInflaterClass)
|
||||
}?.get()?.invoke<VB>(layoutInflater) ?: error("binding failed")
|
||||
setContentView(binding.root)
|
||||
/** 隐藏系统的标题栏 */
|
||||
supportActionBar?.hide()
|
||||
/** 初始化沉浸状态栏 */
|
||||
|
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* MIUINativeNotifyIcon - Fix the native notification bar icon function abandoned by the MIUI development team.
|
||||
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
|
||||
* https://github.com/fankes/MIUINativeNotifyIcon
|
||||
*
|
||||
* 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/10/6.
|
||||
*/
|
||||
package com.fankes.miui.notify.utils.factory
|
||||
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
|
||||
/** 已添加的返回监听事件 */
|
||||
private val onBackPressedCallbacks = HashMap<AppCompatActivity, OnBackPressedCallback>()
|
||||
|
||||
/**
|
||||
* 手动调用返回事件
|
||||
* @param ignored 是否忽略现有返回监听事件立即返回 - 否则将执行返回事件 - 默认否
|
||||
*/
|
||||
fun AppCompatActivity.callOnBackPressed(ignored: Boolean = false) {
|
||||
if (isDestroyed) return
|
||||
onBackPressedCallbacks[this]?.isEnabled = ignored.not()
|
||||
onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加返回监听事件
|
||||
* @param callback 回调事件
|
||||
*/
|
||||
fun AppCompatActivity.addOnBackPressedEvent(callback: OnBackPressedEvent.() -> Unit) {
|
||||
object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
OnBackPressedEvent(this@addOnBackPressedEvent).apply(callback)
|
||||
}
|
||||
}.also { result ->
|
||||
onBackPressedCallbacks.computeIfAbsent(this) {
|
||||
onBackPressedDispatcher.addCallback(result)
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回监听事件实现类
|
||||
* @param instance 当前实例
|
||||
*/
|
||||
class OnBackPressedEvent(private val instance: AppCompatActivity) {
|
||||
|
||||
/** 立即释放返回事件并调用返回功能 */
|
||||
fun releaseEventAndBack() = instance.callOnBackPressed(ignored = true)
|
||||
}
|
@@ -20,7 +20,7 @@
|
||||
*
|
||||
* This file is Created by fankes on 2022/1/7.
|
||||
*/
|
||||
@file:Suppress("DEPRECATION", "PrivateApi", "unused", "ObsoleteSdkInt")
|
||||
@file:Suppress("unused", "ObsoleteSdkInt")
|
||||
|
||||
package com.fankes.miui.notify.utils.factory
|
||||
|
||||
@@ -34,8 +34,9 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.PackageManager.PackageInfoFlags
|
||||
import android.content.res.Configuration
|
||||
import android.content.res.Resources
|
||||
import android.graphics.*
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.net.ConnectivityManager
|
||||
@@ -45,12 +46,16 @@ import android.os.Handler
|
||||
import android.provider.Settings
|
||||
import android.util.Base64
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.content.pm.PackageInfoCompat
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.highcapable.yukihookapi.hook.factory.classOf
|
||||
import com.highcapable.yukihookapi.hook.factory.hasClass
|
||||
import com.highcapable.yukihookapi.hook.factory.method
|
||||
import com.highcapable.yukihookapi.hook.factory.toClassOrNull
|
||||
import com.highcapable.yukihookapi.hook.type.java.StringType
|
||||
import com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication.Companion.appContext
|
||||
import com.topjohnwu.superuser.Shell
|
||||
@@ -58,7 +63,6 @@ import java.io.ByteArrayOutputStream
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
|
||||
/**
|
||||
* 系统深色模式是否开启
|
||||
* @return [Boolean] 是否开启
|
||||
@@ -83,6 +87,12 @@ val Context.isSystemInDarkMode get() = (resources.configuration.uiMode and Confi
|
||||
*/
|
||||
inline val Context.isNotSystemInDarkMode get() = !isSystemInDarkMode
|
||||
|
||||
/**
|
||||
* 系统版本是否高于或等于 Android 13
|
||||
* @return [Boolean] 是否符合条件
|
||||
*/
|
||||
inline val isUpperOfAndroidT get() = Build.VERSION.SDK_INT > Build.VERSION_CODES.S
|
||||
|
||||
/**
|
||||
* 系统版本是否高于或等于 Android 12
|
||||
* @return [Boolean] 是否符合条件
|
||||
@@ -105,7 +115,7 @@ inline val isLowerAndroidR get() = Build.VERSION.SDK_INT < Build.VERSION_CODES.R
|
||||
* 当前设备是否是 MIUI 定制 Android 系统
|
||||
* @return [Boolean] 是否符合条件
|
||||
*/
|
||||
val isMIUI by lazy { ("android.miui.R").hasClass }
|
||||
val isMIUI by lazy { "android.miui.R".hasClass() }
|
||||
|
||||
/**
|
||||
* 当前设备是否不是 MIUI 定制 Android 系统
|
||||
@@ -199,59 +209,79 @@ val miuiFullVersion
|
||||
} else "不是 MIUI 系统"
|
||||
|
||||
/**
|
||||
* 得到安装包信息
|
||||
* @return [PackageInfo]
|
||||
* 获取 [Drawable]
|
||||
* @param resId 属性资源 ID
|
||||
* @return [Drawable]
|
||||
*/
|
||||
val Context.packageInfo get() = packageManager?.getPackageInfo(packageName, 0) ?: PackageInfo()
|
||||
fun Resources.drawableOf(@DrawableRes resId: Int) = ResourcesCompat.getDrawable(this, resId, null) ?: error("Invalid resources")
|
||||
|
||||
/**
|
||||
* 判断应用是否安装
|
||||
* @return [Boolean]
|
||||
*/
|
||||
val String.isInstall
|
||||
get() = safeOfFalse {
|
||||
appContext.packageManager.getPackageInfo(
|
||||
this,
|
||||
PackageManager.GET_UNINSTALLED_PACKAGES
|
||||
)
|
||||
true
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到版本信息
|
||||
* @return [String]
|
||||
*/
|
||||
val Context.versionName get() = packageInfo.versionName ?: ""
|
||||
|
||||
/**
|
||||
* 得到版本号
|
||||
* 获取颜色
|
||||
* @param resId 属性资源 ID
|
||||
* @return [Int]
|
||||
*/
|
||||
val Context.versionCode get() = packageInfo.versionCode
|
||||
fun Resources.colorOf(@ColorRes resId: Int) = ResourcesCompat.getColor(this, resId, null)
|
||||
|
||||
/**
|
||||
* 得到 APP 安装包信息 (兼容)
|
||||
* @param packageName APP 包名
|
||||
* @param flag [PackageInfoFlags]
|
||||
* @return [PackageInfo] or null
|
||||
*/
|
||||
private fun Context.getPackageInfoCompat(packageName: String, flag: Number = 0) = runCatching {
|
||||
@Suppress("DEPRECATION")
|
||||
if (Build.VERSION.SDK_INT >= 33)
|
||||
packageManager?.getPackageInfo(packageName, PackageInfoFlags.of(flag.toLong()))
|
||||
else packageManager?.getPackageInfo(packageName, flag.toInt())
|
||||
}.getOrNull()
|
||||
|
||||
/**
|
||||
* 得到 APP 版本号 (兼容 [PackageInfo.getLongVersionCode])
|
||||
* @return [Int]
|
||||
*/
|
||||
private val PackageInfo.versionCodeCompat get() = PackageInfoCompat.getLongVersionCode(this)
|
||||
|
||||
/**
|
||||
* 判断 APP 是否安装
|
||||
* @param packageName APP 包名
|
||||
* @return [Boolean]
|
||||
*/
|
||||
fun Context.isInstall(packageName: String) = getPackageInfoCompat(packageName)?.let { true } ?: false
|
||||
|
||||
/**
|
||||
* 得到 APP 版本信息
|
||||
* @return [String]
|
||||
*/
|
||||
val Context.appVersionName get() = getPackageInfoCompat(packageName)?.versionName ?: ""
|
||||
|
||||
/**
|
||||
* 得到 APP 版本号
|
||||
* @return [Int]
|
||||
*/
|
||||
val Context.appVersionCode get() = getPackageInfoCompat(packageName)?.versionCodeCompat
|
||||
|
||||
/**
|
||||
* 得到 APP 名称
|
||||
* @param name APP 包名
|
||||
* @param packageName APP 包名 - 默认为当前 APP
|
||||
* @return [String]
|
||||
*/
|
||||
fun Context.findAppName(name: String) =
|
||||
safeOfNothing { packageManager?.getPackageInfo(name, 0)?.applicationInfo?.loadLabel(packageManager).toString() }
|
||||
fun Context.appNameOf(packageName: String = getPackageName()) =
|
||||
getPackageInfoCompat(packageName)?.applicationInfo?.loadLabel(packageManager)?.toString() ?: ""
|
||||
|
||||
/**
|
||||
* 得到 APP 图标
|
||||
* @param name APP 包名
|
||||
* @param packageName APP 包名 - 默认为当前 APP
|
||||
* @return [Drawable] or null
|
||||
*/
|
||||
fun Context.findAppIcon(name: String) =
|
||||
safeOfNull { packageManager?.getPackageInfo(name, 0)?.applicationInfo?.loadIcon(packageManager) }
|
||||
fun Context.appIconOf(packageName: String = getPackageName()) = getPackageInfoCompat(packageName)?.applicationInfo?.loadIcon(packageManager)
|
||||
|
||||
/**
|
||||
* 获取 APP 是否为 DEBUG 版本
|
||||
* @param name APP 包名
|
||||
* @param packageName APP 包名
|
||||
* @return [Boolean]
|
||||
*/
|
||||
fun Context.isAppDebuggable(name: String) =
|
||||
safeOfFalse { (packageManager?.getPackageInfo(name, 0)?.applicationInfo?.flags?.and(ApplicationInfo.FLAG_DEBUGGABLE) ?: 0) != 0 }
|
||||
fun Context.isAppDebuggable(packageName: String) =
|
||||
safeOfFalse { (getPackageInfoCompat(packageName)?.applicationInfo?.flags?.and(ApplicationInfo.FLAG_DEBUGGABLE) ?: 0) != 0 }
|
||||
|
||||
/**
|
||||
* 对数值自动补零
|
||||
@@ -291,8 +321,11 @@ val isNotNoificationEnabled get() = !NotificationManagerCompat.from(appContext).
|
||||
* 网络连接是否正常
|
||||
* @return [Boolean] 网络是否连接
|
||||
*/
|
||||
val isNetWorkSuccess
|
||||
get() = safeOfFalse { appContext.getSystemService<ConnectivityManager>()?.activeNetworkInfo != null }
|
||||
val Context.isNetWorkSuccess
|
||||
get() = safeOfFalse {
|
||||
@Suppress("DEPRECATION")
|
||||
getSystemService<ConnectivityManager>()?.activeNetworkInfo != null
|
||||
}
|
||||
|
||||
/**
|
||||
* dp 转换为 pxInt
|
||||
@@ -313,7 +346,9 @@ fun Number.dpFloat(context: Context) = toFloat() * context.resources.displayMetr
|
||||
* @return [Int] Android < 12 返回 [wallpaperColor]
|
||||
*/
|
||||
val Context.systemAccentColor
|
||||
get() = safeOf(wallpaperColor) { if (isUpperOfAndroidS) resources.getColor(android.R.color.system_accent1_600) else wallpaperColor }
|
||||
get() = safeOf(wallpaperColor) {
|
||||
if (isUpperOfAndroidS) resources.colorOf(android.R.color.system_accent1_600) else wallpaperColor
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取系统壁纸颜色
|
||||
@@ -328,7 +363,7 @@ val Context.wallpaperColor
|
||||
* 获取较浅的颜色
|
||||
* @return [Int]
|
||||
*/
|
||||
val Int.brighter: Int
|
||||
val Int.brighterColor: Int
|
||||
get() {
|
||||
val hsv = FloatArray(3)
|
||||
Color.colorToHSV(this, hsv)
|
||||
@@ -341,7 +376,7 @@ val Int.brighter: Int
|
||||
* 是否为白色
|
||||
* @return [Boolean]
|
||||
*/
|
||||
val Int.isWhite
|
||||
val Int.isWhiteColor
|
||||
get() = safeOfTrue {
|
||||
val r = this and 0xff0000 shr 16
|
||||
val g = this and 0x00ff00 shr 8
|
||||
@@ -411,10 +446,10 @@ fun Bitmap.round(radius: Float): Bitmap = safeOf(default = this) {
|
||||
* @return [String]
|
||||
*/
|
||||
fun findPropString(key: String, default: String = "") = safeOf(default) {
|
||||
(classOf(name = "android.os.SystemProperties").method {
|
||||
"android.os.SystemProperties".toClassOrNull()?.method {
|
||||
name = "get"
|
||||
param(StringType, StringType)
|
||||
}.get().invoke(key, default)) ?: default
|
||||
}?.get()?.invoke(key, default) ?: default
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -490,7 +525,7 @@ fun Context.openBrowser(url: String, packageName: String = "") = runCatching {
|
||||
* @param packageName 包名
|
||||
*/
|
||||
fun Context.openSelfSetting(packageName: String = appContext.packageName) = runCatching {
|
||||
if (packageName.isInstall)
|
||||
if (isInstall(packageName))
|
||||
startActivity(Intent().apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
|
||||
@@ -535,4 +570,7 @@ fun Long.stampToDate(format: String = "yyyy-MM-dd HH:mm:ss") =
|
||||
* @param ms 毫秒 - 默认:150
|
||||
* @param it 方法体
|
||||
*/
|
||||
fun Any?.delayedRun(ms: Long = 150, it: () -> Unit) = runInSafe { Handler().postDelayed({ it() }, ms) }
|
||||
fun Any?.delayedRun(ms: Long = 150, it: () -> Unit) = runInSafe {
|
||||
@Suppress("DEPRECATION")
|
||||
Handler().postDelayed({ it() }, ms)
|
||||
}
|
@@ -91,7 +91,7 @@ object GithubReleaseTool {
|
||||
* @param callback 已连接回调
|
||||
*/
|
||||
private fun checkingInternetConnect(context: Context, callback: () -> Unit) = runInSafe {
|
||||
if (isNetWorkSuccess)
|
||||
if (context.isNetWorkSuccess)
|
||||
OkHttpClient().newBuilder().build().newCall(
|
||||
Request.Builder()
|
||||
.url("https://www.baidu.com")
|
||||
|
@@ -129,12 +129,12 @@ object IconAdaptationTool {
|
||||
)
|
||||
notify(packageName.hashCode(), Notification.Builder(context, NOTIFY_CHANNEL).apply {
|
||||
setShowWhen(true)
|
||||
setContentTitle("您已安装 ${context.findAppName(packageName)}")
|
||||
setContentTitle("您已安装 ${context.appNameOf(packageName)}")
|
||||
setContentText("尚未适配此应用,点按打开在线规则。")
|
||||
setColor(0xFF2993F0.toInt())
|
||||
setAutoCancel(true)
|
||||
setSmallIcon(Icon.createWithBitmap(smallIcon))
|
||||
setLargeIcon(context.findAppIcon(packageName)?.toBitmap())
|
||||
setLargeIcon(context.appIconOf(packageName)?.toBitmap())
|
||||
setContentIntent(
|
||||
PendingIntent.getActivity(
|
||||
context, packageName.hashCode(),
|
||||
@@ -146,7 +146,7 @@ object IconAdaptationTool {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
}.apply {
|
||||
putExtra("isNewAppSupport", true)
|
||||
putExtra("appName", context.findAppName(packageName))
|
||||
putExtra("appName", context.appNameOf(packageName))
|
||||
putExtra("pkgName", packageName)
|
||||
}, if (Build.VERSION.SDK_INT < 31) PendingIntent.FLAG_UPDATE_CURRENT else PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
|
Reference in New Issue
Block a user