From c349ee5dc7984a4df074e0721427f4afaed53e73 Mon Sep 17 00:00:00 2001 From: fankesyooni Date: Fri, 20 Jan 2023 03:09:25 +0800 Subject: [PATCH] Added global app config template function and remove old implementations --- .../data/AppErrorsConfigData.kt | 138 ++++++++++++++++++ .../apperrorstracking/data/ConfigData.kt | 49 +++++++ .../data/enum/AppErrorsConfigType.kt | 42 ++++++ .../data/factory/DataFactory.kt | 104 ------------- .../hook/entity/FrameworkHooker.kt | 28 +++- .../ui/activity/main/ConfigureActivity.kt | 109 +++++++++----- .../utils/tool/FrameworkTool.kt | 13 ++ app/src/main/res/drawable/ic_global.xml | 30 ++++ app/src/main/res/layout/activity_config.xml | 10 ++ app/src/main/res/layout/dia_app_config.xml | 13 +- 10 files changed, 381 insertions(+), 155 deletions(-) create mode 100644 app/src/main/java/com/fankes/apperrorstracking/data/AppErrorsConfigData.kt create mode 100644 app/src/main/java/com/fankes/apperrorstracking/data/enum/AppErrorsConfigType.kt delete mode 100644 app/src/main/java/com/fankes/apperrorstracking/data/factory/DataFactory.kt create mode 100644 app/src/main/res/drawable/ic_global.xml diff --git a/app/src/main/java/com/fankes/apperrorstracking/data/AppErrorsConfigData.kt b/app/src/main/java/com/fankes/apperrorstracking/data/AppErrorsConfigData.kt new file mode 100644 index 0000000..f0266db --- /dev/null +++ b/app/src/main/java/com/fankes/apperrorstracking/data/AppErrorsConfigData.kt @@ -0,0 +1,138 @@ +/* + * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. + * Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com) + * https://github.com/KitsunePie/AppErrorsTracking + * + * 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 2023/1/20. + */ +package com.fankes.apperrorstracking.data + +import com.fankes.apperrorstracking.data.enum.AppErrorsConfigType +import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData + +/** + * 应用配置模版存储控制类 + */ +object AppErrorsConfigData { + + /** 显示错误对话框键值名称 */ + private const val SHOW_ERRORS_DIALOG_APPS = "_show_errors_dialog_apps" + + /** 推送错误通知键值名称 */ + private const val SHOW_ERRORS_NOTIFY_APPS = "_show_errors_notify_apps" + + /** 显示错误 Toast 键值名称 */ + private const val SHOW_ERRORS_TOAST_APPS = "_show_errors_toast_apps" + + /** 什么也不显示键值名称 */ + private const val SHOW_ERRORS_NOTHING_APPS = "_show_errors_nothing_apps" + + /** 全局错误显示类型 */ + private val GLOBAL_SHOW_ERRORS_TYPE = PrefsData("_global_show_errors_type", AppErrorsConfigType.DIALOG.ordinal) + + /** 显示错误对话框的 APP 包名数组 */ + private var showDialogApps = HashSet() + + /** 推送错误通知的 APP 包名数组 */ + private var showNotifyApps = HashSet() + + /** 显示错误 Toast 的 APP 包名数组 */ + private var showToastApps = HashSet() + + /** 什么也不显示的 APP 包名数组 */ + private var showNothingApps = HashSet() + + /** 刷新存储控制类 */ + fun refresh() { + showDialogApps = ConfigData.getStringSet(SHOW_ERRORS_DIALOG_APPS).toHashSet() + showNotifyApps = ConfigData.getStringSet(SHOW_ERRORS_NOTIFY_APPS).toHashSet() + showToastApps = ConfigData.getStringSet(SHOW_ERRORS_TOAST_APPS).toHashSet() + showNothingApps = ConfigData.getStringSet(SHOW_ERRORS_NOTHING_APPS).toHashSet() + } + + /** + * 获取当前 APP 显示错误的类型是否为 [type] + * @param type 当前类型 + * @param packageName 当前 APP 包名 - 不填为全局配置 + * @return [Boolean] + */ + fun isAppShowingType(type: AppErrorsConfigType, packageName: String = "") = + if (packageName.isNotBlank()) when (type) { + AppErrorsConfigType.GLOBAL -> + showDialogApps.contains(packageName).not() && + showNotifyApps.contains(packageName).not() && + showToastApps.contains(packageName).not() && + showNothingApps.contains(packageName).not() + AppErrorsConfigType.DIALOG -> showDialogApps.contains(packageName) + AppErrorsConfigType.NOTIFY -> showNotifyApps.contains(packageName) + AppErrorsConfigType.TOAST -> showToastApps.contains(packageName) + AppErrorsConfigType.NOTHING -> showNothingApps.contains(packageName) + } else ConfigData.getInt(GLOBAL_SHOW_ERRORS_TYPE) == type.ordinal + + /** + * 写入当前 APP 显示错误的类型 + * @param type 当前类型 + * @param packageName 当前 APP 包名 - 不填为全局配置 + */ + fun putAppShowingType(type: AppErrorsConfigType, packageName: String = "") { + if (packageName.isBlank() && type == AppErrorsConfigType.GLOBAL) + error("You can't still specify the \"follow global config\" type when saving the global config") + fun saveAllData() { + ConfigData.putStringSet(SHOW_ERRORS_DIALOG_APPS, showDialogApps) + ConfigData.putStringSet(SHOW_ERRORS_NOTIFY_APPS, showNotifyApps) + ConfigData.putStringSet(SHOW_ERRORS_TOAST_APPS, showToastApps) + ConfigData.putStringSet(SHOW_ERRORS_NOTHING_APPS, showNothingApps) + } + if (packageName.isNotBlank()) when (type) { + AppErrorsConfigType.GLOBAL -> { + showDialogApps.remove(packageName) + showNotifyApps.remove(packageName) + showToastApps.remove(packageName) + showNothingApps.remove(packageName) + saveAllData() + } + AppErrorsConfigType.DIALOG -> { + showDialogApps.add(packageName) + showNotifyApps.remove(packageName) + showToastApps.remove(packageName) + showNothingApps.remove(packageName) + saveAllData() + } + AppErrorsConfigType.NOTIFY -> { + showDialogApps.remove(packageName) + showNotifyApps.add(packageName) + showToastApps.remove(packageName) + showNothingApps.remove(packageName) + saveAllData() + } + AppErrorsConfigType.TOAST -> { + showDialogApps.remove(packageName) + showNotifyApps.remove(packageName) + showToastApps.add(packageName) + showNothingApps.remove(packageName) + saveAllData() + } + AppErrorsConfigType.NOTHING -> { + showDialogApps.remove(packageName) + showNotifyApps.remove(packageName) + showToastApps.remove(packageName) + showNothingApps.add(packageName) + saveAllData() + } + } else ConfigData.putInt(GLOBAL_SHOW_ERRORS_TYPE, type.ordinal) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fankes/apperrorstracking/data/ConfigData.kt b/app/src/main/java/com/fankes/apperrorstracking/data/ConfigData.kt index a6b5568..e234d56 100644 --- a/app/src/main/java/com/fankes/apperrorstracking/data/ConfigData.kt +++ b/app/src/main/java/com/fankes/apperrorstracking/data/ConfigData.kt @@ -67,6 +67,55 @@ object ConfigData { is Context, is PackageParam -> this.instance = instance else -> error("Unknown type for init ConfigData") } + AppErrorsConfigData.refresh() + } + + /** + * 读取 [Set]<[String]> 数据 + * @param key 键值名称 + * @return [Set]<[String]> + */ + internal fun getStringSet(key: String) = when (instance) { + is Context -> (instance as Context).modulePrefs.getStringSet(key, setOf()) + is PackageParam -> (instance as PackageParam).prefs.getStringSet(key, setOf()) + else -> error("Unknown type for get prefs data") + } + + /** + * 存入 [Set]<[String]> 数据 + * @param key 键值名称 + * @param value 键值内容 + */ + internal fun putStringSet(key: String, value: Set) { + when (instance) { + is Context -> (instance as Context).modulePrefs.putStringSet(key, value) + is PackageParam -> loggerW(msg = "Not support for this method") + else -> error("Unknown type for put prefs data") + } + } + + /** + * 读取 [Int] 数据 + * @param data 键值数据模板 + * @return [Int] + */ + internal fun getInt(data: PrefsData) = when (instance) { + is Context -> (instance as Context).modulePrefs.get(data) + is PackageParam -> (instance as PackageParam).prefs.get(data) + else -> error("Unknown type for get prefs data") + } + + /** + * 存入 [Int] 数据 + * @param data 键值数据模板 + * @param value 键值内容 + */ + internal fun putInt(data: PrefsData, value: Int) { + when (instance) { + is Context -> (instance as Context).modulePrefs.put(data, value) + is PackageParam -> loggerW(msg = "Not support for this method") + else -> error("Unknown type for put prefs data") + } } /** diff --git a/app/src/main/java/com/fankes/apperrorstracking/data/enum/AppErrorsConfigType.kt b/app/src/main/java/com/fankes/apperrorstracking/data/enum/AppErrorsConfigType.kt new file mode 100644 index 0000000..10705d1 --- /dev/null +++ b/app/src/main/java/com/fankes/apperrorstracking/data/enum/AppErrorsConfigType.kt @@ -0,0 +1,42 @@ +/* + * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. + * Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com) + * https://github.com/KitsunePie/AppErrorsTracking + * + * 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 2023/1/20. + */ +package com.fankes.apperrorstracking.data.enum + +/** + * 应用配置模版类型定义类 + */ +enum class AppErrorsConfigType { + /** 跟随全局配置 */ + GLOBAL, + + /** 对话框 */ + DIALOG, + + /** 通知 */ + NOTIFY, + + /** Toast */ + TOAST, + + /** 什么也不显示 */ + NOTHING +} \ No newline at end of file diff --git a/app/src/main/java/com/fankes/apperrorstracking/data/factory/DataFactory.kt b/app/src/main/java/com/fankes/apperrorstracking/data/factory/DataFactory.kt deleted file mode 100644 index 4a5e147..0000000 --- a/app/src/main/java/com/fankes/apperrorstracking/data/factory/DataFactory.kt +++ /dev/null @@ -1,104 +0,0 @@ -/* - * AppErrorsTracking - Added more features to app's crash dialog, fixed custom rom deleted dialog, the best experience to Android developer. - * Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com) - * https://github.com/KitsunePie/AppErrorsTracking - * - * 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/6/8. - */ -@file:Suppress("unused") - -package com.fankes.apperrorstracking.data.factory - -import android.content.Context -import com.highcapable.yukihookapi.hook.factory.modulePrefs -import com.highcapable.yukihookapi.hook.param.PackageParam - -/** - * 获取此 APP 是否配置显示错误对话框 - * @param packageName APP 包名 - */ -fun PackageParam.isAppShowErrorsDialog(packageName: String) = prefs.getBoolean("${packageName}_show_errors_dialog", true) - -/** - * 获取此 APP 是否配置显示错误通知推送 - * @param packageName APP 包名 - */ -fun PackageParam.isAppShowErrorsNotify(packageName: String) = prefs.getBoolean("${packageName}_show_errors_notify", false) - -/** - * 获取此 APP 是否配置显示错误 Toast 提示 - * @param packageName APP 包名 - */ -fun PackageParam.isAppShowErrorsToast(packageName: String) = prefs.getBoolean("${packageName}_show_errors_toast", false) - -/** - * 获取此 APP 是否配置不显示任何提示 - * @param packageName APP 包名 - */ -fun PackageParam.isAppShowNothing(packageName: String) = prefs.getBoolean("${packageName}_show_nothing", false) - -/** - * 获取此 APP 是否配置显示错误对话框 - * @param packageName APP 包名 - */ -fun Context.isAppShowErrorsDialog(packageName: String) = modulePrefs.getBoolean("${packageName}_show_errors_dialog", true) - -/** - * 获取此 APP 是否配置显示错误通知推送 - * @param packageName APP 包名 - */ -fun Context.isAppShowErrorsNotify(packageName: String) = modulePrefs.getBoolean("${packageName}_show_errors_notify", false) - -/** - * 获取此 APP 是否配置显示错误 Toast 提示 - * @param packageName APP 包名 - */ -fun Context.isAppShowErrorsToast(packageName: String) = modulePrefs.getBoolean("${packageName}_show_errors_toast", false) - -/** - * 获取此 APP 是否配置不显示任何提示 - * @param packageName APP 包名 - */ -fun Context.isAppShowNothing(packageName: String) = modulePrefs.getBoolean("${packageName}_show_nothing", false) - -/** - * 设置此 APP 是否配置显示错误对话框 - * @param packageName APP 包名 - * @param isApply 是否设置 - */ -fun Context.putAppShowErrorsDialog(packageName: String, isApply: Boolean) = modulePrefs.putBoolean("${packageName}_show_errors_dialog", isApply) - -/** - * 设置此 APP 是否配置显示错误通知推送 - * @param packageName APP 包名 - * @param isApply 是否设置 - */ -fun Context.putAppShowErrorsNotify(packageName: String, isApply: Boolean) = modulePrefs.putBoolean("${packageName}_show_errors_notify", isApply) - -/** - * 设置此 APP 是否配置显示错误 Toast 提示 - * @param packageName APP 包名 - * @param isApply 是否设置 - */ -fun Context.putAppShowErrorsToast(packageName: String, isApply: Boolean) = modulePrefs.putBoolean("${packageName}_show_errors_toast", isApply) - -/** - * 设置此 APP 是否配置不显示任何提示 - * @param packageName APP 包名 - * @param isApply 是否设置 - */ -fun Context.putAppShowNothing(packageName: String, isApply: Boolean) = modulePrefs.putBoolean("${packageName}_show_nothing", isApply) \ No newline at end of file diff --git a/app/src/main/java/com/fankes/apperrorstracking/hook/entity/FrameworkHooker.kt b/app/src/main/java/com/fankes/apperrorstracking/hook/entity/FrameworkHooker.kt index 073215f..91a1ea3 100644 --- a/app/src/main/java/com/fankes/apperrorstracking/hook/entity/FrameworkHooker.kt +++ b/app/src/main/java/com/fankes/apperrorstracking/hook/entity/FrameworkHooker.kt @@ -28,6 +28,7 @@ import android.content.Intent import android.content.pm.ApplicationInfo import android.os.Build import android.os.Message +import android.os.SystemClock import android.util.ArrayMap import androidx.core.graphics.drawable.IconCompat import androidx.core.graphics.drawable.toBitmap @@ -37,12 +38,10 @@ import com.fankes.apperrorstracking.bean.AppErrorsDisplayBean import com.fankes.apperrorstracking.bean.AppErrorsInfoBean import com.fankes.apperrorstracking.bean.AppInfoBean import com.fankes.apperrorstracking.bean.MutedErrorsAppBean +import com.fankes.apperrorstracking.data.AppErrorsConfigData import com.fankes.apperrorstracking.data.AppErrorsRecordData import com.fankes.apperrorstracking.data.ConfigData -import com.fankes.apperrorstracking.data.factory.isAppShowErrorsDialog -import com.fankes.apperrorstracking.data.factory.isAppShowErrorsNotify -import com.fankes.apperrorstracking.data.factory.isAppShowErrorsToast -import com.fankes.apperrorstracking.data.factory.isAppShowNothing +import com.fankes.apperrorstracking.data.enum.AppErrorsConfigType import com.fankes.apperrorstracking.locale.LocaleString import com.fankes.apperrorstracking.ui.activity.errors.AppErrorsDisplayActivity import com.fankes.apperrorstracking.ui.activity.errors.AppErrorsRecordActivity @@ -178,6 +177,13 @@ object FrameworkHooker : YukiBaseHooker() { onCreate { AppErrorsRecordData.init(context = this) } } FrameworkTool.Host.with(instance = this) { + onRefreshFrameworkPrefsData { + /** 必要的延迟防止 Sp 存储不刷新 */ + SystemClock.sleep(100) + /** 刷新存储类 */ + AppErrorsConfigData.refresh() + if (prefs.isPreferencesAvailable.not()) loggerW(msg = "Cannot refreshing app errors config data, preferences is not available") + } onOpenAppUsedFramework { appContext?.openApp(it.first, it.second) loggerI(msg = "Opened \"${it.first}\"${it.second.takeIf { e -> e > 0 }?.let { e -> " --user $e" } ?: ""}") @@ -310,10 +316,16 @@ object FrameworkHooker : YukiBaseHooker() { loggerE(msg = "AppErrorsTracking has crashed itself, please see the Android Runtime Exception in console") } ConfigData.isEnableAppConfigTemplate -> when { - isAppShowNothing(packageName) -> {} - isAppShowErrorsNotify(packageName) -> showAppErrorsWithNotify() - isAppShowErrorsToast(packageName) -> showAppErrorsWithToast() - isAppShowErrorsDialog(packageName) -> showAppErrorsWithDialog() + AppErrorsConfigData.isAppShowingType(AppErrorsConfigType.GLOBAL, packageName) -> when { + AppErrorsConfigData.isAppShowingType(AppErrorsConfigType.DIALOG) -> showAppErrorsWithDialog() + AppErrorsConfigData.isAppShowingType(AppErrorsConfigType.NOTIFY) -> showAppErrorsWithNotify() + AppErrorsConfigData.isAppShowingType(AppErrorsConfigType.TOAST) -> showAppErrorsWithToast() + AppErrorsConfigData.isAppShowingType(AppErrorsConfigType.NOTHING) -> {} + } + AppErrorsConfigData.isAppShowingType(AppErrorsConfigType.DIALOG, packageName) -> showAppErrorsWithDialog() + AppErrorsConfigData.isAppShowingType(AppErrorsConfigType.NOTIFY, packageName) -> showAppErrorsWithNotify() + AppErrorsConfigData.isAppShowingType(AppErrorsConfigType.TOAST, packageName) -> showAppErrorsWithToast() + AppErrorsConfigData.isAppShowingType(AppErrorsConfigType.NOTHING, packageName) -> {} } else -> showAppErrorsWithDialog() } diff --git a/app/src/main/java/com/fankes/apperrorstracking/ui/activity/main/ConfigureActivity.kt b/app/src/main/java/com/fankes/apperrorstracking/ui/activity/main/ConfigureActivity.kt index 7d01f6d..f73df43 100644 --- a/app/src/main/java/com/fankes/apperrorstracking/ui/activity/main/ConfigureActivity.kt +++ b/app/src/main/java/com/fankes/apperrorstracking/ui/activity/main/ConfigureActivity.kt @@ -24,7 +24,8 @@ package com.fankes.apperrorstracking.ui.activity.main import androidx.core.view.isVisible import com.fankes.apperrorstracking.bean.AppFiltersBean import com.fankes.apperrorstracking.bean.AppInfoBean -import com.fankes.apperrorstracking.data.factory.* +import com.fankes.apperrorstracking.data.AppErrorsConfigData +import com.fankes.apperrorstracking.data.enum.AppErrorsConfigType import com.fankes.apperrorstracking.databinding.ActivityConfigBinding import com.fankes.apperrorstracking.databinding.AdapterAppInfoBinding import com.fankes.apperrorstracking.databinding.DiaAppConfigBinding @@ -50,30 +51,23 @@ class ConfigureActivity : BaseActivity() { override fun onCreate() { binding.titleBackIcon.setOnClickListener { finish() } + binding.globalIcon.setOnClickListener { + showAppConfigDialog(LocaleString.globalConfig, isShowGlobalConfig = false) { type -> + AppErrorsConfigData.putAppShowingType(type) + onChanged?.invoke() + } + } binding.batchIcon.setOnClickListener { - showDialog { - title = LocaleString.batchOperations - confirmButton { - val config0 = binding.configRadio0.isChecked - val config1 = binding.configRadio1.isChecked - val config2 = binding.configRadio2.isChecked - val config3 = binding.configRadio3.isChecked - showDialog { - title = LocaleString.notice - msg = LocaleString.areYouSureApplySiteApps(listData.size) - confirmButton { - listData.takeIf { it.isNotEmpty() }?.forEach { - putAppShowErrorsDialog(it.packageName, config0) - putAppShowErrorsNotify(it.packageName, config1) - putAppShowErrorsToast(it.packageName, config2) - putAppShowNothing(it.packageName, config3) - } - onChanged?.invoke() - } - cancelButton() + showAppConfigDialog(LocaleString.batchOperationsNumber(listData.size), isNotSetDefaultValue = true) { type -> + showDialog { + title = LocaleString.notice + msg = LocaleString.areYouSureApplySiteApps(listData.size) + confirmButton { + listData.takeIf { it.isNotEmpty() }?.forEach { AppErrorsConfigData.putAppShowingType(type, it.packageName) } + onChanged?.invoke() } + cancelButton() } - cancelButton() } } binding.filterIcon.setOnClickListener { @@ -110,10 +104,11 @@ class ConfigureActivity : BaseActivity() { binding.appIcon.setImageDrawable(bean.icon) binding.appNameText.text = bean.name binding.configTypeText.text = when { - isAppShowErrorsDialog(bean.packageName) -> LocaleString.showErrorsDialog - isAppShowErrorsNotify(bean.packageName) -> LocaleString.showErrorsNotify - isAppShowErrorsToast(bean.packageName) -> LocaleString.showErrorsToast - isAppShowNothing(bean.packageName) -> LocaleString.showNothing + AppErrorsConfigData.isAppShowingType(AppErrorsConfigType.GLOBAL, bean.packageName) -> LocaleString.followGlobalConfig + AppErrorsConfigData.isAppShowingType(AppErrorsConfigType.DIALOG, bean.packageName) -> LocaleString.showErrorsDialog + AppErrorsConfigData.isAppShowingType(AppErrorsConfigType.NOTIFY, bean.packageName) -> LocaleString.showErrorsNotify + AppErrorsConfigData.isAppShowingType(AppErrorsConfigType.TOAST, bean.packageName) -> LocaleString.showErrorsToast + AppErrorsConfigData.isAppShowingType(AppErrorsConfigType.NOTHING, bean.packageName) -> LocaleString.showNothing else -> "Unknown type" } } @@ -121,20 +116,9 @@ class ConfigureActivity : BaseActivity() { }.apply { onChanged = { notifyDataSetChanged() } } setOnItemClickListener { _, _, p, _ -> listData[p].also { bean -> - showDialog { - title = bean.name - binding.configRadio0.isChecked = isAppShowErrorsDialog(bean.packageName) - binding.configRadio1.isChecked = isAppShowErrorsNotify(bean.packageName) - binding.configRadio2.isChecked = isAppShowErrorsToast(bean.packageName) - binding.configRadio3.isChecked = isAppShowNothing(bean.packageName) - confirmButton { - putAppShowErrorsDialog(bean.packageName, binding.configRadio0.isChecked) - putAppShowErrorsNotify(bean.packageName, binding.configRadio1.isChecked) - putAppShowErrorsToast(bean.packageName, binding.configRadio2.isChecked) - putAppShowNothing(bean.packageName, binding.configRadio3.isChecked) - onChanged?.invoke() - } - cancelButton() + showAppConfigDialog(bean.name, bean.packageName) { type -> + AppErrorsConfigData.putAppShowingType(type, bean.packageName) + onChanged?.invoke() } } } @@ -152,9 +136,53 @@ class ConfigureActivity : BaseActivity() { refreshData() } + /** + * 显示应用配置对话框 + * @param title 对话框标题 + * @param packageName APP 包名 - 默认空 (空时使用全局配置的默认值) + * @param isNotSetDefaultValue 是否不设置选项的默认值 - 默认否 + * @param isShowGlobalConfig 是否显示跟随全局配置选项 - 默认是 + * @param result 回调类型结果 + */ + private fun showAppConfigDialog( + title: String, + packageName: String = "", + isNotSetDefaultValue: Boolean = false, + isShowGlobalConfig: Boolean = true, + result: (AppErrorsConfigType) -> Unit + ) { + showDialog { + this.title = title + binding.configRadio0.isVisible = isShowGlobalConfig + if (isNotSetDefaultValue.not()) { + if (isShowGlobalConfig) binding.configRadio0.isChecked = + AppErrorsConfigData.isAppShowingType(AppErrorsConfigType.GLOBAL, packageName) + binding.configRadio1.isChecked = AppErrorsConfigData.isAppShowingType(AppErrorsConfigType.DIALOG, packageName) + binding.configRadio2.isChecked = AppErrorsConfigData.isAppShowingType(AppErrorsConfigType.NOTIFY, packageName) + binding.configRadio3.isChecked = AppErrorsConfigData.isAppShowingType(AppErrorsConfigType.TOAST, packageName) + binding.configRadio4.isChecked = AppErrorsConfigData.isAppShowingType(AppErrorsConfigType.NOTHING, packageName) + } + confirmButton { + result( + when { + binding.configRadio0.isChecked -> AppErrorsConfigType.GLOBAL + binding.configRadio1.isChecked -> AppErrorsConfigType.DIALOG + binding.configRadio2.isChecked -> AppErrorsConfigType.NOTIFY + binding.configRadio3.isChecked -> AppErrorsConfigType.TOAST + binding.configRadio4.isChecked -> AppErrorsConfigType.NOTHING + else -> error("Invalid config type") + } + ) + FrameworkTool.refreshFrameworkPrefsData(context) + } + cancelButton() + } + } + /** 刷新列表数据 */ private fun refreshData() { binding.listProgressView.isVisible = true + binding.globalIcon.isVisible = false binding.batchIcon.isVisible = false binding.filterIcon.isVisible = false binding.listView.isVisible = false @@ -176,6 +204,7 @@ class ConfigureActivity : BaseActivity() { onChanged?.invoke() binding.listView.post { binding.listView.setSelection(0) } binding.listProgressView.isVisible = false + binding.globalIcon.isVisible = true binding.batchIcon.isVisible = listData.isNotEmpty() binding.filterIcon.isVisible = true binding.listView.isVisible = listData.isNotEmpty() diff --git a/app/src/main/java/com/fankes/apperrorstracking/utils/tool/FrameworkTool.kt b/app/src/main/java/com/fankes/apperrorstracking/utils/tool/FrameworkTool.kt index 1d679fb..a2452d3 100644 --- a/app/src/main/java/com/fankes/apperrorstracking/utils/tool/FrameworkTool.kt +++ b/app/src/main/java/com/fankes/apperrorstracking/utils/tool/FrameworkTool.kt @@ -44,6 +44,7 @@ object FrameworkTool { /** 系统框架包名 */ const val SYSTEM_FRAMEWORK_NAME = "android" + private const val CALL_REFRESH_HOST_PREFS_DATA = "call_refresh_host_prefs_data" private const val CALL_APP_ERRORS_DATA_GET = "call_app_errors_data_get" private const val CALL_MUTED_ERRORS_APP_DATA_GET = "call_muted_app_errors_data_get" private const val CALL_APP_ERRORS_DATA_CLEAR = "call_app_errors_data_clear" @@ -83,6 +84,12 @@ object FrameworkTool { */ fun with(instance: PackageParam, initiate: Host.() -> Unit) = apply { this.instance = instance }.apply(initiate) + /** + * 通知系统框架刷新存储的数据 + * @param callback 回调 + */ + fun onRefreshFrameworkPrefsData(callback: () -> Unit) = instance?.dataChannel?.wait(CALL_REFRESH_HOST_PREFS_DATA) { callback() } + /** * 监听使用系统框架打开 APP * @param result 回调包名和用户 ID @@ -244,6 +251,12 @@ object FrameworkTool { fun checkingActivated(context: Context, result: (Boolean) -> Unit) = context.dataChannel(SYSTEM_FRAMEWORK_NAME).checkingVersionEquals(result = result) + /** + * 通知系统框架刷新存储的数据 + * @param context 实例 + */ + fun refreshFrameworkPrefsData(context: Context) = context.dataChannel(SYSTEM_FRAMEWORK_NAME).put(CALL_REFRESH_HOST_PREFS_DATA) + /** * 使用系统框架打开 [packageName] * @param context 实例 diff --git a/app/src/main/res/drawable/ic_global.xml b/app/src/main/res/drawable/ic_global.xml new file mode 100644 index 0000000..5e3c18e --- /dev/null +++ b/app/src/main/res/drawable/ic_global.xml @@ -0,0 +1,30 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_config.xml b/app/src/main/res/layout/activity_config.xml index 9a0922d..af04b9c 100644 --- a/app/src/main/res/layout/activity_config.xml +++ b/app/src/main/res/layout/activity_config.xml @@ -57,6 +57,16 @@ android:textSize="11.5sp" /> + + + +