diff --git a/app/src/main/java/com/fankes/apperrorstracking/application/AppErrorsApplication.kt b/app/src/main/java/com/fankes/apperrorstracking/application/AppErrorsApplication.kt
index ab07144..f92c773 100644
--- a/app/src/main/java/com/fankes/apperrorstracking/application/AppErrorsApplication.kt
+++ b/app/src/main/java/com/fankes/apperrorstracking/application/AppErrorsApplication.kt
@@ -22,6 +22,7 @@
package com.fankes.apperrorstracking.application
import androidx.appcompat.app.AppCompatDelegate
+import com.fankes.apperrorstracking.data.ConfigData
import com.fankes.apperrorstracking.locale.LocaleString
import com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication
@@ -33,5 +34,7 @@ class AppErrorsApplication : ModuleApplication() {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
/** 绑定 I18n */
LocaleString.bind(instance = this)
+ /** 装载存储控制类 */
+ ConfigData.init(instance = this)
}
}
\ 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
new file mode 100644
index 0000000..52b196b
--- /dev/null
+++ b/app/src/main/java/com/fankes/apperrorstracking/data/ConfigData.kt
@@ -0,0 +1,156 @@
+/*
+ * 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/10/1.
+ */
+@file:Suppress("MemberVisibilityCanBePrivate")
+
+package com.fankes.apperrorstracking.data
+
+import android.content.Context
+import android.widget.CompoundButton
+import com.highcapable.yukihookapi.hook.factory.modulePrefs
+import com.highcapable.yukihookapi.hook.log.loggerW
+import com.highcapable.yukihookapi.hook.param.PackageParam
+import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData
+
+/**
+ * 全局配置存储控制类
+ */
+object ConfigData {
+
+ /** 显示开发者提示 */
+ val SHOW_DEVELOPER_NOTICE = PrefsData("_show_developer_notice", true)
+
+ /** 仅对前台应用显示错误对话框 */
+ val ENABLE_ONLY_SHOW_ERRORS_IN_FRONT = PrefsData("_enable_only_show_errors_in_front", false)
+
+ /** 仅对应用主进程显示错误对话框 */
+ val ENABLE_ONLY_SHOW_ERRORS_IN_MAIN = PrefsData("_enable_only_show_errors_in_main", false)
+
+ /** 错误对话框始终显示“重新打开”选项 */
+ val ENABLE_ALWAYS_SHOWS_REOPEN_APP_OPTIONS = PrefsData("_enable_always_shows_reopen_app_options", false)
+
+ /** 启用应用配置模板 */
+ val ENABLE_APP_CONFIG_TEMPLATE = PrefsData("_enable_app_config_template", false)
+
+ /** 当前实例 - [Context] or [PackageParam] */
+ private var instance: Any? = null
+
+ /**
+ * 初始化存储控制类
+ * @param instance 实例 - 只能是 [Context] or [PackageParam]
+ * @throws IllegalStateException 如果类型错误
+ */
+ fun init(instance: Any) {
+ when (instance) {
+ is Context, is PackageParam -> this.instance = instance
+ else -> error("Unknown type for init ConfigData")
+ }
+ }
+
+ /**
+ * 读取 [Boolean] 数据
+ * @param data 键值数据模板
+ * @return [Boolean]
+ */
+ private fun getBoolean(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")
+ }
+
+ /**
+ * 存入 [Boolean] 数据
+ * @param data 键值数据模板
+ * @param value 键值内容
+ */
+ private fun putBoolean(data: PrefsData, value: Boolean) {
+ 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")
+ }
+ }
+
+ /**
+ * 绑定到 [CompoundButton] 自动设置选中状态
+ * @param data 键值数据模板
+ * @param onChange 当改变时回调
+ */
+ fun CompoundButton.bind(data: PrefsData, onChange: (Boolean) -> Unit = {}) {
+ isChecked = getBoolean(data).also(onChange)
+ setOnCheckedChangeListener { button, isChecked ->
+ if (button.isPressed) {
+ putBoolean(data, isChecked)
+ onChange(isChecked)
+ }
+ }
+ }
+
+ /**
+ * 是否显示开发者提示
+ * @return [Boolean]
+ */
+ var isShowDeveloperNotice
+ get() = getBoolean(SHOW_DEVELOPER_NOTICE)
+ set(value) {
+ putBoolean(SHOW_DEVELOPER_NOTICE, value)
+ }
+
+ /**
+ * 仅对前台应用显示错误对话框
+ * @return [Boolean]
+ */
+ var isEnableOnlyShowErrorsInFront
+ get() = getBoolean(ENABLE_ONLY_SHOW_ERRORS_IN_FRONT)
+ set(value) {
+ putBoolean(ENABLE_ONLY_SHOW_ERRORS_IN_FRONT, value)
+ }
+
+ /**
+ * 仅对应用主进程显示错误对话框
+ * @return [Boolean]
+ */
+ var isEnableOnlyShowErrorsInMain
+ get() = getBoolean(ENABLE_ONLY_SHOW_ERRORS_IN_MAIN)
+ set(value) {
+ putBoolean(ENABLE_ONLY_SHOW_ERRORS_IN_MAIN, value)
+ }
+
+ /**
+ * 错误对话框始终显示“重新打开”选项
+ * @return [Boolean]
+ */
+ var isEnableAlwaysShowsReopenAppOptions
+ get() = getBoolean(ENABLE_ALWAYS_SHOWS_REOPEN_APP_OPTIONS)
+ set(value) {
+ putBoolean(ENABLE_ALWAYS_SHOWS_REOPEN_APP_OPTIONS, value)
+ }
+
+ /**
+ * 启用应用配置模板
+ * @return [Boolean]
+ */
+ var isEnableAppConfigTemplate
+ get() = getBoolean(ENABLE_APP_CONFIG_TEMPLATE)
+ set(value) {
+ putBoolean(ENABLE_APP_CONFIG_TEMPLATE, value)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/fankes/apperrorstracking/data/DataConst.kt b/app/src/main/java/com/fankes/apperrorstracking/data/DataConst.kt
deleted file mode 100644
index e4d5c9d..0000000
--- a/app/src/main/java/com/fankes/apperrorstracking/data/DataConst.kt
+++ /dev/null
@@ -1,34 +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/5/14.
- */
-package com.fankes.apperrorstracking.data
-
-import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData
-
-object DataConst {
-
- val SHOW_DEVELOPER_NOTICE = PrefsData("_show_developer_notice", true)
-
- val ENABLE_ONLY_SHOW_ERRORS_IN_FRONT = PrefsData("_enable_only_show_errors_in_front", false)
- val ENABLE_ONLY_SHOW_ERRORS_IN_MAIN = PrefsData("_enable_only_show_errors_in_main", false)
- val ENABLE_ALWAYS_SHOWS_REOPEN_APP_OPTIONS = PrefsData("_enable_always_shows_reopen_app_options", false)
- val ENABLE_APP_CONFIG_TEMPLATE = PrefsData("_enable_app_config_template", false)
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/fankes/apperrorstracking/hook/factory/DataFactory.kt b/app/src/main/java/com/fankes/apperrorstracking/data/factory/DataFactory.kt
similarity index 98%
rename from app/src/main/java/com/fankes/apperrorstracking/hook/factory/DataFactory.kt
rename to app/src/main/java/com/fankes/apperrorstracking/data/factory/DataFactory.kt
index c5b1310..4a5e147 100644
--- a/app/src/main/java/com/fankes/apperrorstracking/hook/factory/DataFactory.kt
+++ b/app/src/main/java/com/fankes/apperrorstracking/data/factory/DataFactory.kt
@@ -21,7 +21,7 @@
*/
@file:Suppress("unused")
-package com.fankes.apperrorstracking.hook.factory
+package com.fankes.apperrorstracking.data.factory
import android.content.Context
import com.highcapable.yukihookapi.hook.factory.modulePrefs
diff --git a/app/src/main/java/com/fankes/apperrorstracking/hook/HookEntry.kt b/app/src/main/java/com/fankes/apperrorstracking/hook/HookEntry.kt
index 4b0468b..85e0e20 100644
--- a/app/src/main/java/com/fankes/apperrorstracking/hook/HookEntry.kt
+++ b/app/src/main/java/com/fankes/apperrorstracking/hook/HookEntry.kt
@@ -21,6 +21,7 @@
*/
package com.fankes.apperrorstracking.hook
+import com.fankes.apperrorstracking.data.ConfigData
import com.fankes.apperrorstracking.hook.entity.FrameworkHooker
import com.fankes.apperrorstracking.locale.LocaleString
import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed
@@ -40,6 +41,7 @@ class HookEntry : IYukiHookXposedInit {
override fun onHook() = encase {
loadSystem {
LocaleString.bind(instance = this)
+ ConfigData.init(instance = this)
loadHooker(FrameworkHooker)
}
}
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 792b511..dbb207b 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
@@ -37,10 +37,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.DataConst
-import com.fankes.apperrorstracking.hook.factory.isAppShowErrorsNotify
-import com.fankes.apperrorstracking.hook.factory.isAppShowErrorsToast
-import com.fankes.apperrorstracking.hook.factory.isAppShowNothing
+import com.fankes.apperrorstracking.data.ConfigData
+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.locale.LocaleString
import com.fankes.apperrorstracking.ui.activity.errors.AppErrorsDisplayActivity
import com.fankes.apperrorstracking.ui.activity.errors.AppErrorsRecordActivity
@@ -238,9 +238,6 @@ object FrameworkHooker : YukiBaseHooker() {
/** 崩溃标题 */
val errorTitle = if (isRepeating) LocaleString.aerrRepeatedTitle(appName) else LocaleString.aerrTitle(appName)
-
- /** 是否始终显示重新打开按钮 */
- val isAlwaysShowsReopenApp = prefs.get(DataConst.ENABLE_ALWAYS_SHOWS_REOPEN_APP_OPTIONS)
/** 打印错误日志 */
if (isApp) loggerE(
msg = "App \"$packageName\"${if (packageName != processName) " --process \"$processName\"" else ""}" +
@@ -254,7 +251,7 @@ object FrameworkHooker : YukiBaseHooker() {
/** 判断是否为已忽略的 APP */
if (mutedErrorsIfUnlockApps.contains(packageName) || mutedErrorsIfRestartApps.contains(packageName)) return@afterHook
/** 判断配置模块启用状态 */
- if (prefs.get(DataConst.ENABLE_APP_CONFIG_TEMPLATE)) {
+ if (ConfigData.isEnableAppConfigTemplate) {
if (isAppShowNothing(packageName)) return@afterHook
if (isAppShowErrorsNotify(packageName)) {
context.pushNotify(
@@ -274,11 +271,10 @@ object FrameworkHooker : YukiBaseHooker() {
}
}
/** 判断是否为后台进程 */
- if ((isBackgroundProcess || context.isAppCanOpened(packageName).not())
- && prefs.get(DataConst.ENABLE_ONLY_SHOW_ERRORS_IN_FRONT)
- ) return@afterHook
+ if ((isBackgroundProcess || context.isAppCanOpened(packageName).not()) && ConfigData.isEnableOnlyShowErrorsInFront)
+ return@afterHook
/** 判断是否为主进程 */
- if (isMainProcess.not() && prefs.get(DataConst.ENABLE_ONLY_SHOW_ERRORS_IN_MAIN)) return@afterHook
+ if (isMainProcess.not() && ConfigData.isEnableOnlyShowErrorsInMain) return@afterHook
/** 启动错误对话框显示窗口 */
AppErrorsDisplayActivity.start(
context, AppErrorsDisplayBean(
@@ -287,7 +283,7 @@ object FrameworkHooker : YukiBaseHooker() {
appName = appName,
title = errorTitle,
isShowAppInfoButton = isApp,
- isShowReopenButton = isApp && (isRepeating.not() || isAlwaysShowsReopenApp)
+ isShowReopenButton = isApp && (isRepeating.not() || ConfigData.isEnableAlwaysShowsReopenAppOptions)
&& context.isAppCanOpened(packageName) && isMainProcess,
isShowCloseAppButton = isApp
)
@@ -308,4 +304,4 @@ object FrameworkHooker : YukiBaseHooker() {
}
}
}
-}
+}
\ No newline at end of file
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 3615afa..94890cd 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,11 +24,11 @@ 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.databinding.ActivityConfigBinding
import com.fankes.apperrorstracking.databinding.AdapterAppInfoBinding
import com.fankes.apperrorstracking.databinding.DiaAppConfigBinding
import com.fankes.apperrorstracking.databinding.DiaAppsFilterBinding
-import com.fankes.apperrorstracking.hook.factory.*
import com.fankes.apperrorstracking.locale.LocaleString
import com.fankes.apperrorstracking.ui.activity.base.BaseActivity
import com.fankes.apperrorstracking.utils.factory.appIconOf
diff --git a/app/src/main/java/com/fankes/apperrorstracking/ui/activity/main/MainActivity.kt b/app/src/main/java/com/fankes/apperrorstracking/ui/activity/main/MainActivity.kt
index f64ea6f..a78e42f 100644
--- a/app/src/main/java/com/fankes/apperrorstracking/ui/activity/main/MainActivity.kt
+++ b/app/src/main/java/com/fankes/apperrorstracking/ui/activity/main/MainActivity.kt
@@ -27,7 +27,8 @@ import android.os.Build
import androidx.core.view.isVisible
import com.fankes.apperrorstracking.BuildConfig
import com.fankes.apperrorstracking.R
-import com.fankes.apperrorstracking.data.DataConst
+import com.fankes.apperrorstracking.data.ConfigData
+import com.fankes.apperrorstracking.data.ConfigData.bind
import com.fankes.apperrorstracking.databinding.ActivityMainBinding
import com.fankes.apperrorstracking.locale.LocaleString
import com.fankes.apperrorstracking.ui.activity.base.BaseActivity
@@ -36,7 +37,6 @@ import com.fankes.apperrorstracking.ui.activity.errors.AppErrorsRecordActivity
import com.fankes.apperrorstracking.utils.factory.*
import com.fankes.apperrorstracking.utils.tool.FrameworkTool
import com.highcapable.yukihookapi.YukiHookAPI
-import com.highcapable.yukihookapi.hook.factory.modulePrefs
class MainActivity : BaseActivity() {
@@ -50,27 +50,11 @@ class MainActivity : BaseActivity() {
binding.mainTextVersion.text = LocaleString.moduleVersion(BuildConfig.VERSION_NAME)
binding.mainTextSystemVersion.text =
LocaleString.systemVersion("${Build.VERSION.RELEASE} (API ${Build.VERSION.SDK_INT}) ${Build.DISPLAY}")
- binding.onlyShowErrorsInFrontSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_ONLY_SHOW_ERRORS_IN_FRONT)
- binding.onlyShowErrorsInMainProcessSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_ONLY_SHOW_ERRORS_IN_MAIN)
- binding.alwaysShowsReopenAppOptionsSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_ALWAYS_SHOWS_REOPEN_APP_OPTIONS)
- binding.enableAppsConfigsTemplateSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_APP_CONFIG_TEMPLATE)
- binding.mgrAppsConfigsTemplateButton.isVisible = modulePrefs.get(DataConst.ENABLE_APP_CONFIG_TEMPLATE)
- binding.onlyShowErrorsInFrontSwitch.setOnCheckedChangeListener { btn, b ->
- if (btn.isPressed.not()) return@setOnCheckedChangeListener
- modulePrefs.put(DataConst.ENABLE_ONLY_SHOW_ERRORS_IN_FRONT, b)
- }
- binding.onlyShowErrorsInMainProcessSwitch.setOnCheckedChangeListener { btn, b ->
- if (btn.isPressed.not()) return@setOnCheckedChangeListener
- modulePrefs.put(DataConst.ENABLE_ONLY_SHOW_ERRORS_IN_MAIN, b)
- }
- binding.alwaysShowsReopenAppOptionsSwitch.setOnCheckedChangeListener { btn, b ->
- if (btn.isPressed.not()) return@setOnCheckedChangeListener
- modulePrefs.put(DataConst.ENABLE_ALWAYS_SHOWS_REOPEN_APP_OPTIONS, b)
- }
- binding.enableAppsConfigsTemplateSwitch.setOnCheckedChangeListener { btn, b ->
- if (btn.isPressed.not()) return@setOnCheckedChangeListener
- binding.mgrAppsConfigsTemplateButton.isVisible = b
- modulePrefs.put(DataConst.ENABLE_APP_CONFIG_TEMPLATE, b)
+ binding.onlyShowErrorsInFrontSwitch.bind(ConfigData.ENABLE_ONLY_SHOW_ERRORS_IN_FRONT)
+ binding.onlyShowErrorsInMainProcessSwitch.bind(ConfigData.ENABLE_ONLY_SHOW_ERRORS_IN_MAIN)
+ binding.alwaysShowsReopenAppOptionsSwitch.bind(ConfigData.ENABLE_ALWAYS_SHOWS_REOPEN_APP_OPTIONS)
+ binding.enableAppsConfigsTemplateSwitch.bind(ConfigData.ENABLE_APP_CONFIG_TEMPLATE) {
+ binding.mgrAppsConfigsTemplateButton.isVisible = it
}
/** 设置桌面图标显示隐藏 */
binding.hideIconInLauncherSwitch.isChecked = isLauncherIconShowing.not()
@@ -88,11 +72,11 @@ class MainActivity : BaseActivity() {
/** 项目地址按钮点击事件 */
binding.titleGithubIcon.setOnClickListener { openBrowser(url = "https://github.com/KitsunePie/AppErrorsTracking") }
/** 显示开发者提示 */
- if (modulePrefs.get(DataConst.SHOW_DEVELOPER_NOTICE))
+ if (ConfigData.isShowDeveloperNotice)
showDialog {
title = LocaleString.developerNotice
msg = LocaleString.developerNoticeTip
- confirmButton(LocaleString.gotIt) { modulePrefs.put(DataConst.SHOW_DEVELOPER_NOTICE, value = false) }
+ confirmButton(LocaleString.gotIt) { ConfigData.isShowDeveloperNotice = false }
noCancelable()
}
}