mirror of
https://github.com/KitsunePie/AppErrorsTracking.git
synced 2025-09-01 08:45:16 +08:00
Added global app config template function and remove old implementations
This commit is contained in:
@@ -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
|
||||
* <https://www.gnu.org/licenses/>
|
||||
*
|
||||
* 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<String>()
|
||||
|
||||
/** 推送错误通知的 APP 包名数组 */
|
||||
private var showNotifyApps = HashSet<String>()
|
||||
|
||||
/** 显示错误 Toast 的 APP 包名数组 */
|
||||
private var showToastApps = HashSet<String>()
|
||||
|
||||
/** 什么也不显示的 APP 包名数组 */
|
||||
private var showNothingApps = HashSet<String>()
|
||||
|
||||
/** 刷新存储控制类 */
|
||||
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)
|
||||
}
|
||||
}
|
@@ -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<String>) {
|
||||
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<Int>) = 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<Int>, 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")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
* <https://www.gnu.org/licenses/>
|
||||
*
|
||||
* 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
|
||||
}
|
@@ -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
|
||||
* <https://www.gnu.org/licenses/>
|
||||
*
|
||||
* 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)
|
@@ -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()
|
||||
}
|
||||
|
@@ -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<ActivityConfigBinding>() {
|
||||
|
||||
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<DiaAppConfigBinding> {
|
||||
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<ActivityConfigBinding>() {
|
||||
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<ActivityConfigBinding>() {
|
||||
}.apply { onChanged = { notifyDataSetChanged() } }
|
||||
setOnItemClickListener { _, _, p, _ ->
|
||||
listData[p].also { bean ->
|
||||
showDialog<DiaAppConfigBinding> {
|
||||
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<ActivityConfigBinding>() {
|
||||
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<DiaAppConfigBinding> {
|
||||
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<ActivityConfigBinding>() {
|
||||
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()
|
||||
|
@@ -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 实例
|
||||
|
30
app/src/main/res/drawable/ic_global.xml
Normal file
30
app/src/main/res/drawable/ic_global.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M18,6H8C6.895,6 6,6.895 6,8V18C6,19.105 6.895,20 8,20H18C19.105,20 20,19.105 20,18V8C20,6.895 19.105,6 18,6Z"
|
||||
android:strokeWidth="4"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeLineJoin="round" />
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M18,28H8C6.895,28 6,28.895 6,30V40C6,41.105 6.895,42 8,42H18C19.105,42 20,41.105 20,40V30C20,28.895 19.105,28 18,28Z"
|
||||
android:strokeWidth="4"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeLineJoin="round" />
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M40,6H30C28.895,6 28,6.895 28,8V18C28,19.105 28.895,20 30,20H40C41.105,20 42,19.105 42,18V8C42,6.895 41.105,6 40,6Z"
|
||||
android:strokeWidth="4"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeLineJoin="round" />
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M40,28H30C28.895,28 28,28.895 28,30V40C28,41.105 28.895,42 30,42H40C41.105,42 42,41.105 42,40V30C42,28.895 41.105,28 40,28Z"
|
||||
android:strokeWidth="4"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeLineJoin="round" />
|
||||
</vector>
|
@@ -57,6 +57,16 @@
|
||||
android:textSize="11.5sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/global_icon"
|
||||
android:layout_width="23dp"
|
||||
android:layout_height="23dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:src="@drawable/ic_global"
|
||||
android:tint="@color/colorTextGray"
|
||||
android:tooltipText="@string/global_config"
|
||||
android:visibility="gone" />
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/batch_icon"
|
||||
android:layout_width="25dp"
|
||||
|
@@ -27,27 +27,34 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="true"
|
||||
android:text="@string/show_errors_dialog"
|
||||
android:text="@string/follow_global_config"
|
||||
app:buttonTint="@color/colorPrimaryAccent" />
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
android:id="@+id/config_radio_1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/show_errors_notify"
|
||||
android:text="@string/show_errors_dialog"
|
||||
app:buttonTint="@color/colorPrimaryAccent" />
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
android:id="@+id/config_radio_2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/show_errors_toast"
|
||||
android:text="@string/show_errors_notify"
|
||||
app:buttonTint="@color/colorPrimaryAccent" />
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
android:id="@+id/config_radio_3"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/show_errors_toast"
|
||||
app:buttonTint="@color/colorPrimaryAccent" />
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
android:id="@+id/config_radio_4"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/show_nothing"
|
||||
app:buttonTint="@color/colorPrimaryAccent" />
|
||||
</RadioGroup>
|
||||
|
Reference in New Issue
Block a user