diff --git a/.idea/misc.xml b/.idea/misc.xml index 1964724..819e6c6 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -9,6 +9,7 @@ + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1893fd5..fb91119 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -4,6 +4,7 @@ package="com.fankes.miui.notify"> + Unit - ) = runSafe(msg = "GetSmallIconOnSet") { - if (iconDrawable == null) return@runSafe + ) = runInSafe(msg = "GetSmallIconOnSet") { + if (iconDrawable == null) return@runInSafe /** 如果没开启修复 APP 的彩色图标 */ - if (!prefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)) return@runSafe + if (!prefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)) return@runInSafe /** 获取通知对象 - 由于 MIUI 的版本迭代不规范性可能是空的 */ expandedNf?.also { notifyInstance -> /** 判断是 MIUI 样式就停止 Hook */ if (context.isMiuiNotifyStyle) { it(notifyInstance.findAppIcon(context).toBitmap()) - return@runSafe + return@runInSafe } /** 判断是否不是灰度图标 */ val isNotGrayscaleIcon = notifyInstance.isXmsf || !isGrayscaleIcon(context, iconDrawable) @@ -343,11 +343,11 @@ class HookEntry : YukiHookXposedInitProxy { expandedNf: StatusBarNotification?, iconImageView: ImageView, isExpanded: Boolean - ) = runSafe(msg = "AutoSetAppIconOnSet") { + ) = runInSafe(msg = "AutoSetAppIconOnSet") { /** 判断是 MIUI 样式就停止 Hook */ - if (context.isMiuiNotifyStyle) return@runSafe + if (context.isMiuiNotifyStyle) return@runInSafe /** 如果没开启修复 APP 的彩色图标 */ - if (!prefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)) return@runSafe + if (!prefs.getBoolean(ENABLE_COLOR_ICON_HOOK, default = true)) return@runInSafe /** 获取通知对象 - 由于 MIUI 的版本迭代不规范性可能是空的 */ expandedNf?.let { notifyInstance -> diff --git a/app/src/main/java/com/fankes/miui/notify/ui/activity/MainActivity.kt b/app/src/main/java/com/fankes/miui/notify/ui/activity/MainActivity.kt index 12d5d49..2852224 100644 --- a/app/src/main/java/com/fankes/miui/notify/ui/activity/MainActivity.kt +++ b/app/src/main/java/com/fankes/miui/notify/ui/activity/MainActivity.kt @@ -46,6 +46,7 @@ import com.fankes.miui.notify.hook.HookConst.HOOK_STATUS_ICON_COUNT import com.fankes.miui.notify.params.IconPackParams import com.fankes.miui.notify.ui.activity.base.BaseActivity import com.fankes.miui.notify.utils.factory.* +import com.fankes.miui.notify.utils.tool.GithubReleaseTool import com.fankes.miui.notify.utils.tool.SystemUITool import com.highcapable.yukihookapi.hook.factory.isXposedModuleActive import com.highcapable.yukihookapi.hook.factory.modulePrefs @@ -65,6 +66,14 @@ class MainActivity : BaseActivity() { /** 设置文本 */ binding.mainTextVersion.text = "模块版本:$moduleVersion" binding.mainTextMiuiVersion.text = "系统版本:$miuiFullVersion" + /** 检查更新 */ + GithubReleaseTool.checkingForUpdate(context = this, moduleVersion) { version, function -> + binding.mainTextReleaseVersion.apply { + text = "点击更新 $version" + isVisible = true + setOnClickListener { function() } + } + } when { /** 判断是否为 MIUI 系统 */ isNotMIUI -> @@ -233,9 +242,7 @@ class MainActivity : BaseActivity() { /** 重启按钮点击事件 */ binding.titleRestartIcon.setOnClickListener { SystemUITool.restartSystemUI(context = this) } /** 项目地址按钮点击事件 */ - binding.titleGithubIcon.setOnClickListener { - openBrowser(url = "https://github.com/fankes/MIUINativeNotifyIcon") - } + binding.titleGithubIcon.setOnClickListener { openBrowser(url = "https://github.com/fankes/MIUINativeNotifyIcon") } /** 恰饭! */ binding.linkWithFollowMe.setOnClickListener { openBrowser(url = "https://www.coolapk.com/u/876977", packageName = "com.coolapk.market") @@ -286,9 +293,7 @@ class MainActivity : BaseActivity() { /** 防止顶栈一样重叠在自己的 APP 中 */ flags = Intent.FLAG_ACTIVITY_NEW_TASK }) - }.onFailure { - toast(msg = "启动失败,请手动调整设置") - } + }.onFailure { toast(msg = "启动失败,请手动调整设置") } isWarnDialogShowing = false } cancelButton { isWarnDialogShowing = false } diff --git a/app/src/main/java/com/fankes/miui/notify/utils/factory/DialogBuilderFactory.kt b/app/src/main/java/com/fankes/miui/notify/utils/factory/DialogBuilderFactory.kt index 8377949..2da31e9 100644 --- a/app/src/main/java/com/fankes/miui/notify/utils/factory/DialogBuilderFactory.kt +++ b/app/src/main/java/com/fankes/miui/notify/utils/factory/DialogBuilderFactory.kt @@ -73,8 +73,8 @@ class DialogBuilder(val context: Context, private val isUseBlackTheme: Boolean) init { if (isUsingAndroidX) - runCatching { instanceAndroidX = MaterialAlertDialogBuilder(context) } - else runCatching { + runInSafe { instanceAndroidX = MaterialAlertDialogBuilder(context) } + else runInSafe { instanceAndroid = android.app.AlertDialog.Builder( context, if (isUseBlackTheme) android.R.style.Theme_Material_Dialog else android.R.style.Theme_Material_Light_Dialog @@ -85,8 +85,8 @@ class DialogBuilder(val context: Context, private val isUseBlackTheme: Boolean) /** 设置对话框不可关闭 */ fun noCancelable() { if (isUsingAndroidX) - runCatching { instanceAndroidX?.setCancelable(false) } - else runCatching { instanceAndroid?.setCancelable(false) } + runInSafe { instanceAndroidX?.setCancelable(false) } + else runInSafe { instanceAndroid?.setCancelable(false) } } /** 设置对话框标题 */ @@ -94,8 +94,8 @@ class DialogBuilder(val context: Context, private val isUseBlackTheme: Boolean) get() = "" set(value) { if (isUsingAndroidX) - runCatching { instanceAndroidX?.setTitle(value) } - else runCatching { instanceAndroid?.setTitle(value) } + runInSafe { instanceAndroidX?.setTitle(value) } + else runInSafe { instanceAndroid?.setTitle(value) } } /** 设置对话框消息内容 */ @@ -103,8 +103,8 @@ class DialogBuilder(val context: Context, private val isUseBlackTheme: Boolean) get() = "" set(value) { if (isUsingAndroidX) - runCatching { instanceAndroidX?.setMessage(value) } - else runCatching { instanceAndroid?.setMessage(value) } + runInSafe { instanceAndroidX?.setMessage(value) } + else runInSafe { instanceAndroid?.setMessage(value) } } /** 设置进度条对话框消息内容 */ @@ -145,8 +145,8 @@ class DialogBuilder(val context: Context, private val isUseBlackTheme: Boolean) */ fun confirmButton(text: String = "确定", it: () -> Unit = {}) { if (isUsingAndroidX) - runCatching { instanceAndroidX?.setPositiveButton(text) { _, _ -> it() } } - else runCatching { instanceAndroid?.setPositiveButton(text) { _, _ -> it() } } + runInSafe { instanceAndroidX?.setPositiveButton(text) { _, _ -> it() } } + else runInSafe { instanceAndroid?.setPositiveButton(text) { _, _ -> it() } } } /** @@ -156,8 +156,8 @@ class DialogBuilder(val context: Context, private val isUseBlackTheme: Boolean) */ fun cancelButton(text: String = "取消", it: () -> Unit = {}) { if (isUsingAndroidX) - runCatching { instanceAndroidX?.setNegativeButton(text) { _, _ -> it() } } - else runCatching { instanceAndroid?.setNegativeButton(text) { _, _ -> it() } } + runInSafe { instanceAndroidX?.setNegativeButton(text) { _, _ -> it() } } + else runInSafe { instanceAndroid?.setNegativeButton(text) { _, _ -> it() } } } /** @@ -167,21 +167,21 @@ class DialogBuilder(val context: Context, private val isUseBlackTheme: Boolean) */ fun neutralButton(text: String = "更多", it: () -> Unit = {}) { if (isUsingAndroidX) - runCatching { instanceAndroidX?.setNeutralButton(text) { _, _ -> it() } } - else runCatching { instanceAndroid?.setNeutralButton(text) { _, _ -> it() } } + runInSafe { instanceAndroidX?.setNeutralButton(text) { _, _ -> it() } } + else runInSafe { instanceAndroid?.setNeutralButton(text) { _, _ -> it() } } } /** 取消对话框 */ fun cancel() = dialogInstance?.cancel() /** 显示对话框 */ - internal fun show() { - if (isUsingAndroidX) runCatching { + internal fun show() = + if (isUsingAndroidX) runInSafe { instanceAndroidX?.create()?.apply { customLayoutView?.let { setView(it) } dialogInstance = this }?.show() - } else runCatching { + } else runInSafe { instanceAndroid?.create()?.apply { customLayoutView?.let { setView(it) } window?.setBackgroundDrawable( @@ -197,5 +197,4 @@ class DialogBuilder(val context: Context, private val isUseBlackTheme: Boolean) dialogInstance = this }?.show() } - } } \ No newline at end of file diff --git a/app/src/main/java/com/fankes/miui/notify/utils/factory/ExceptionFactory.kt b/app/src/main/java/com/fankes/miui/notify/utils/factory/ExceptionFactory.kt index ceedde6..94f6b8c 100644 --- a/app/src/main/java/com/fankes/miui/notify/utils/factory/ExceptionFactory.kt +++ b/app/src/main/java/com/fankes/miui/notify/utils/factory/ExceptionFactory.kt @@ -78,6 +78,6 @@ inline fun safeOf(default: T, result: () -> T) = try { * @param msg 出错输出的消息 - 默认为空 * @param block 正常回调 */ -inline fun T.runSafe(msg: String = "", block: () -> Unit) { +inline fun T.runInSafe(msg: String = "", block: () -> Unit) { runCatching(block).onFailure { if (msg.isNotBlank()) loggerE(msg = msg, e = it) } } \ No newline at end of file diff --git a/app/src/main/java/com/fankes/miui/notify/utils/factory/FunctionFactory.kt b/app/src/main/java/com/fankes/miui/notify/utils/factory/FunctionFactory.kt index 00de7ca..77f4f28 100644 --- a/app/src/main/java/com/fankes/miui/notify/utils/factory/FunctionFactory.kt +++ b/app/src/main/java/com/fankes/miui/notify/utils/factory/FunctionFactory.kt @@ -35,12 +35,14 @@ import android.content.res.Configuration import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.Color +import android.net.ConnectivityManager import android.net.Uri import android.os.Build import android.provider.Settings import android.util.Base64 import android.widget.Toast import androidx.core.app.NotificationManagerCompat +import androidx.core.content.getSystemService import com.fankes.miui.notify.application.MNNApplication.Companion.appContext import com.google.android.material.snackbar.Snackbar import com.highcapable.yukihookapi.hook.factory.classOf @@ -221,6 +223,13 @@ val Context.versionCode get() = packageInfo.versionCode */ val isNotNoificationEnabled get() = !NotificationManagerCompat.from(appContext).areNotificationsEnabled() +/** + * 网络连接是否正常 + * @return [Boolean] 网络是否连接 + */ +val isNetWorkSuccess + get() = safeOfFalse { appContext.getSystemService()?.activeNetworkInfo != null } + /** * dp 转换为 pxInt * @param context 使用的实例 @@ -352,11 +361,25 @@ fun Context.openBrowser(url: String, packageName: String = "") = runCatching { else snake(msg = "启动系统浏览器失败") } +/** + * 跳转 APP 自身设置界面 + * @param packageName 包名 + */ +fun Context.openSelfSetting(packageName: String = appContext.packageName) = runCatching { + if (packageName.isInstall) + startActivity(Intent().apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK + action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS + data = Uri.fromParts("package", packageName, null) + }) + else toast(msg = "你没有安装此应用") +}.onFailure { toast(msg = "启动 $packageName 应用信息失败") } + /** * 复制到剪贴板 * @param content 要复制的文本 */ -fun Context.copyToClipboard(content: String) = runSafe { +fun Context.copyToClipboard(content: String) = runInSafe { (getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager).apply { setPrimaryClip(ClipData.newPlainText(null, content)) (primaryClip?.getItemAt(0)?.text ?: "").also { diff --git a/app/src/main/java/com/fankes/miui/notify/utils/tool/GithubReleaseTool.kt b/app/src/main/java/com/fankes/miui/notify/utils/tool/GithubReleaseTool.kt new file mode 100644 index 0000000..2761da5 --- /dev/null +++ b/app/src/main/java/com/fankes/miui/notify/utils/tool/GithubReleaseTool.kt @@ -0,0 +1,128 @@ +/* + * 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. + *

+ * + * 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 + * + * + * This file is Created by fankes on 2022/3/20. + */ +package com.fankes.miui.notify.utils.tool + +import android.app.Activity +import android.content.Context +import com.fankes.miui.notify.utils.factory.* +import okhttp3.* +import org.json.JSONObject +import java.io.IOException +import java.io.Serializable + +/** + * 获取 Github Release 最新版本工具类 + */ +object GithubReleaseTool { + + /** 仓库作者 */ + private const val repoAuthor = "fankes" + + /** 仓库名称 */ + private const val repoName = "MIUINativeNotifyIcon" + + /** + * 获取最新版本信息 + * @param context 实例 + * @param version 当前版本 + * @param it 成功后回调 - ([String] 最新版本,[Function] 更新对话框方法体) + */ + fun checkingForUpdate(context: Context, version: String, it: (String, () -> Unit) -> Unit) = checkingInternetConnect(context) { + OkHttpClient().newBuilder().build().newCall( + Request.Builder() + .url("https://api.github.com/repos/$repoAuthor/$repoName/releases/latest") + .get() + .build() + ).enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) {} + + override fun onResponse(call: Call, response: Response) = runInSafe { + JSONObject(response.body?.string() ?: "").apply { + GithubReleaseBean( + name = getString("name"), + htmlUrl = getString("html_url"), + content = getString("body"), + date = getString("published_at").replace(oldValue = "T", newValue = " ").replace(oldValue = "Z", newValue = "") + ).apply { + fun showUpdate() = context.showDialog { + title = "最新版本 $name" + msg = "发布于 $date\n\n" + + "更新日志\n\n" + content + confirmButton(text = "更新") { context.openBrowser(htmlUrl) } + cancelButton() + } + if (name != version) (context as? Activity?)?.runOnUiThread { + showUpdate() + it(name) { showUpdate() } + } + } + } + } + }) + } + + /** + * 检查网络连接情况 + * @param context 实例 + * @param it 已连接回调 + */ + private fun checkingInternetConnect(context: Context, it: () -> Unit) = runInSafe { + if (isNetWorkSuccess) + OkHttpClient().newBuilder().build().newCall( + Request.Builder() + .url("https://www.baidu.com") + .get() + .build() + ).enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + (context as? Activity?)?.runOnUiThread { + context.showDialog { + title = "网络不可用" + msg = "模块的联网权限可能已被禁用,请开启联网权限以定期检查更新。" + confirmButton(text = "去开启") { context.openSelfSetting() } + cancelButton() + noCancelable() + } + } + } + + override fun onResponse(call: Call, response: Response) = runInSafe { + (context as? Activity?)?.runOnUiThread { runInSafe { it() } } + } + }) + } + + /** + * Github Release bean + * @param name 版本名称 + * @param htmlUrl 网页地址 + * @param content 更新日志 + * @param date 发布时间 + */ + private data class GithubReleaseBean( + var name: String, + var htmlUrl: String, + var content: String, + var date: String + ) : Serializable +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_orange_round.xml b/app/src/main/res/drawable/bg_orange_round.xml new file mode 100755 index 0000000..043d002 --- /dev/null +++ b/app/src/main/res/drawable/bg_orange_round.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 840142a..6fbd83b 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -91,15 +91,37 @@ android:textColor="@color/white" android:textSize="18sp" /> - + android:gravity="center|start" + android:orientation="horizontal"> + + + + +