Modify merge DataConst to ConfigData and move DataFactory to data/factory

This commit is contained in:
2022-10-02 00:25:16 +08:00
parent abf6103b9d
commit 1862faf637
8 changed files with 182 additions and 75 deletions

View File

@@ -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)
}
}

View File

@@ -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
* <https://www.gnu.org/licenses/>
*
* 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<Boolean>) = 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<Boolean>, 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<Boolean>, 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)
}
}

View File

@@ -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
* <https://www.gnu.org/licenses/>
*
* 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)
}

View File

@@ -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

View File

@@ -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)
}
}

View File

@@ -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() {
}
}
}
}
}

View File

@@ -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

View File

@@ -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<ActivityMainBinding>() {
@@ -50,27 +50,11 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
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<ActivityMainBinding>() {
/** 项目地址按钮点击事件 */
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()
}
}