mirror of
https://github.com/KitsunePie/AppErrorsTracking.git
synced 2025-09-01 16:55:18 +08:00
Added Apps Configs Template function
This commit is contained in:
@@ -52,11 +52,9 @@ Added more features to app's crash dialog, fixed custom rom deleted dialog, the
|
||||
|
||||
## Future
|
||||
|
||||
此项目依然在开发中,现在未解决的问题和包含的问题如下
|
||||
此项目依然在开发中,正在开发的功能如下
|
||||
|
||||
- 应用配置模板功能
|
||||
|
||||
- 更多功能 (计划内)
|
||||
- 应用异常统计信息功能
|
||||
|
||||
## License
|
||||
|
||||
|
@@ -54,6 +54,11 @@
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity
|
||||
android:name=".ui.activity.main.ConfigureActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="behind" />
|
||||
|
||||
<activity
|
||||
android:name=".ui.activity.errors.AppErrorsRecordActivity"
|
||||
android:exported="true"
|
||||
|
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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/4.
|
||||
*/
|
||||
package com.fankes.apperrorstracking.bean
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* 应用过滤条件 bean
|
||||
* @param name 名称或包名
|
||||
* @param isContainsSystem 是否包含系统应用
|
||||
*/
|
||||
data class AppFiltersBean(var name: String = "", var isContainsSystem: Boolean = false) : Serializable
|
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.fankes.apperrorstracking.bean
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* 应用信息 bean
|
||||
* @param icon 图标
|
||||
* @param name APP 名称
|
||||
* @param packageName APP 包名
|
||||
*/
|
||||
data class AppInfoBean(var icon: Drawable? = null, var name: String, var packageName: String) : Serializable
|
@@ -28,4 +28,5 @@ object DataConst {
|
||||
val ENABLE_HIDE_ICON = PrefsData("_hide_icon", false)
|
||||
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_APP_CONFIG_TEMPLATE = PrefsData("_enable_app_config_template", false)
|
||||
}
|
@@ -26,12 +26,16 @@ package com.fankes.apperrorstracking.hook.entity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Message
|
||||
import com.fankes.apperrorstracking.BuildConfig
|
||||
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.isAppShowErrorsToast
|
||||
import com.fankes.apperrorstracking.hook.factory.isAppShowNothing
|
||||
import com.fankes.apperrorstracking.locale.LocaleString
|
||||
import com.fankes.apperrorstracking.ui.activity.errors.AppErrorsDisplayActivity
|
||||
import com.fankes.apperrorstracking.utils.factory.appName
|
||||
@@ -107,6 +111,21 @@ object FrameworkHooker : YukiBaseHooker() {
|
||||
mutedErrorsIfUnlockApps.clear()
|
||||
mutedErrorsIfRestartApps.clear()
|
||||
}
|
||||
onPushAppListData { filters ->
|
||||
arrayListOf<AppInfoBean>().apply {
|
||||
appContext.packageManager.getInstalledPackages(PackageManager.GET_CONFIGURATIONS).also { info ->
|
||||
(if (filters.name.isNotBlank())
|
||||
info.filter { it.packageName.contains(filters.name) || appContext.appName(it.packageName).contains(filters.name) }
|
||||
else info).let { result ->
|
||||
if (filters.isContainsSystem.not()) result.filter { (it.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM) == 0 }
|
||||
else result
|
||||
}.sortedByDescending { it.lastUpdateTime }
|
||||
.forEach { add(AppInfoBean(name = appContext.appName(it.packageName), packageName = it.packageName)) }
|
||||
/** 移除模块自身 */
|
||||
removeIf { it.packageName == BuildConfig.APPLICATION_ID }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,6 +206,9 @@ object FrameworkHooker : YukiBaseHooker() {
|
||||
|
||||
/** 是否短时内重复错误 */
|
||||
val isRepeating = AppErrorDialog_DataClass.clazz.field { name = "repeating" }.get(errData).boolean()
|
||||
|
||||
/** 崩溃标题 */
|
||||
val errorTitle = if (isRepeating) LocaleString.aerrRepeatedTitle(appName) else LocaleString.aerrTitle(appName)
|
||||
/** 打印错误日志 */
|
||||
if (isApp) loggerE(
|
||||
msg = "App \"$packageName\"${if (packageName != processName) " --process \"$processName\"" else ""}" +
|
||||
@@ -205,13 +227,21 @@ object FrameworkHooker : YukiBaseHooker() {
|
||||
) return@afterHook
|
||||
/** 判断是否为主进程 */
|
||||
if (isMainProcess.not() && prefs.get(DataConst.ENABLE_ONLY_SHOW_ERRORS_IN_MAIN)) return@afterHook
|
||||
/** 判断配置模块启用状态 */
|
||||
if (prefs.get(DataConst.ENABLE_APP_CONFIG_TEMPLATE)) {
|
||||
if (isAppShowNothing(packageName)) return@afterHook
|
||||
if (isAppShowErrorsToast(packageName)) {
|
||||
context.toast(errorTitle)
|
||||
return@afterHook
|
||||
}
|
||||
}
|
||||
/** 启动错误对话框显示窗口 */
|
||||
AppErrorsDisplayActivity.start(
|
||||
context, AppErrorsDisplayBean(
|
||||
packageName = packageName,
|
||||
processName = processName,
|
||||
appName = appName,
|
||||
title = if (isRepeating) LocaleString.aerrRepeatedTitle(appName) else LocaleString.aerrTitle(appName),
|
||||
title = errorTitle,
|
||||
isShowAppInfoButton = isApp,
|
||||
isShowReopenButton = isApp && isRepeating.not() && context.isAppCanOpened(packageName) && isMainProcess,
|
||||
isShowCloseAppButton = isApp
|
||||
|
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.hook.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 是否配置显示错误 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 是否配置显示错误 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 是否配置显示错误 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)
|
@@ -346,4 +346,46 @@ object LocaleString {
|
||||
|
||||
/** @string Automatic generated */
|
||||
fun areYouSureUnmuteAll(vararg objArrs: Any) = R.string.are_you_sure_unmute_all.bind(*objArrs)
|
||||
|
||||
/** @string Automatic generated */
|
||||
val filterByCondition get() = filterByCondition()
|
||||
|
||||
/** @string Automatic generated */
|
||||
fun filterByCondition(vararg objArrs: Any) = R.string.filter_by_condition.bind(*objArrs)
|
||||
|
||||
/** @string Automatic generated */
|
||||
val clearFilters get() = clearFilters()
|
||||
|
||||
/** @string Automatic generated */
|
||||
fun clearFilters(vararg objArrs: Any) = R.string.clear_filters.bind(*objArrs)
|
||||
|
||||
/** @string Automatic generated */
|
||||
val resultCount get() = resultCount()
|
||||
|
||||
/** @string Automatic generated */
|
||||
fun resultCount(vararg objArrs: Any) = R.string.result_count.bind(*objArrs)
|
||||
|
||||
/** @string Automatic generated */
|
||||
val loading get() = loading()
|
||||
|
||||
/** @string Automatic generated */
|
||||
fun loading(vararg objArrs: Any) = R.string.loading.bind(*objArrs)
|
||||
|
||||
/** @string Automatic generated */
|
||||
val showErrorsDialog get() = showErrorsDialog()
|
||||
|
||||
/** @string Automatic generated */
|
||||
fun showErrorsDialog(vararg objArrs: Any) = R.string.show_errors_dialog.bind(*objArrs)
|
||||
|
||||
/** @string Automatic generated */
|
||||
val showErrorsToast get() = showErrorsToast()
|
||||
|
||||
/** @string Automatic generated */
|
||||
fun showErrorsToast(vararg objArrs: Any) = R.string.show_errors_toast.bind(*objArrs)
|
||||
|
||||
/** @string Automatic generated */
|
||||
val showNothing get() = showNothing()
|
||||
|
||||
/** @string Automatic generated */
|
||||
fun showNothing(vararg objArrs: Any) = R.string.show_nothing.bind(*objArrs)
|
||||
}
|
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* 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/4.
|
||||
*/
|
||||
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.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.appIcon
|
||||
import com.fankes.apperrorstracking.utils.factory.bindAdapter
|
||||
import com.fankes.apperrorstracking.utils.factory.showDialog
|
||||
import com.fankes.apperrorstracking.utils.tool.FrameworkTool
|
||||
|
||||
class ConfigureActivity : BaseActivity<ActivityConfigBinding>() {
|
||||
|
||||
/** 过滤条件 */
|
||||
private var appFilters = AppFiltersBean()
|
||||
|
||||
/** 回调适配器改变 */
|
||||
private var onChanged: (() -> Unit)? = null
|
||||
|
||||
/** 全部的 APP 信息 */
|
||||
private val listData = ArrayList<AppInfoBean>()
|
||||
|
||||
override fun onCreate() {
|
||||
binding.titleBackIcon.setOnClickListener { onBackPressed() }
|
||||
binding.filterIcon.setOnClickListener {
|
||||
showDialog<DiaAppsFilterBinding> {
|
||||
title = LocaleString.filterByCondition
|
||||
binding.containsSystemSwitch.isChecked = appFilters.isContainsSystem
|
||||
binding.appFiltersEdit.apply {
|
||||
requestFocus()
|
||||
invalidate()
|
||||
if (appFilters.name.isNotBlank()) {
|
||||
setText(appFilters.name)
|
||||
setSelection(appFilters.name.length)
|
||||
}
|
||||
}
|
||||
confirmButton {
|
||||
appFilters.isContainsSystem = binding.containsSystemSwitch.isChecked
|
||||
appFilters.name = binding.appFiltersEdit.text.toString().trim()
|
||||
refreshData()
|
||||
}
|
||||
cancelButton()
|
||||
if (appFilters.name.isNotBlank())
|
||||
neutralButton(LocaleString.clearFilters) {
|
||||
appFilters.isContainsSystem = binding.containsSystemSwitch.isChecked
|
||||
appFilters.name = ""
|
||||
refreshData()
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.listView.apply {
|
||||
bindAdapter {
|
||||
onBindDatas { listData }
|
||||
onBindViews<AdapterAppInfoBinding> { binding, position ->
|
||||
listData[position].also { bean ->
|
||||
binding.appIcon.setImageDrawable(bean.icon)
|
||||
binding.appNameText.text = bean.name
|
||||
binding.configTypeText.text = when {
|
||||
isAppShowErrorsDialog(bean.packageName) -> LocaleString.showErrorsDialog
|
||||
isAppShowErrorsToast(bean.packageName) -> LocaleString.showErrorsToast
|
||||
isAppShowNothing(bean.packageName) -> LocaleString.showNothing
|
||||
else -> "Unknown type"
|
||||
}
|
||||
}
|
||||
}
|
||||
}.apply { onChanged = { notifyDataSetChanged() } }
|
||||
setOnItemClickListener { _, _, p, _ ->
|
||||
listData[p].also { bean ->
|
||||
showDialog<DiaAppConfigBinding> {
|
||||
title = bean.name
|
||||
binding.configRadio1.isChecked = isAppShowErrorsDialog(bean.packageName)
|
||||
binding.configRadio2.isChecked = isAppShowErrorsToast(bean.packageName)
|
||||
binding.configRadio3.isChecked = isAppShowNothing(bean.packageName)
|
||||
confirmButton {
|
||||
putAppShowErrorsDialog(bean.packageName, binding.configRadio1.isChecked)
|
||||
putAppShowErrorsToast(bean.packageName, binding.configRadio2.isChecked)
|
||||
putAppShowNothing(bean.packageName, binding.configRadio3.isChecked)
|
||||
onChanged?.invoke()
|
||||
}
|
||||
cancelButton()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** 开始刷新数据 */
|
||||
refreshData()
|
||||
}
|
||||
|
||||
/** 刷新列表数据 */
|
||||
private fun refreshData() {
|
||||
binding.listProgressView.isVisible = true
|
||||
binding.filterIcon.isVisible = false
|
||||
binding.listView.isVisible = false
|
||||
binding.listNoDataView.isVisible = false
|
||||
binding.titleCountText.text = LocaleString.loading
|
||||
FrameworkTool.fetchAppListData(context = this, appFilters) {
|
||||
listData.clear()
|
||||
Thread {
|
||||
it.takeIf { e -> e.isNotEmpty() }?.forEach { e ->
|
||||
listData.add(e)
|
||||
e.icon = appIcon(e.packageName)
|
||||
}
|
||||
runOnUiThread {
|
||||
onChanged?.invoke()
|
||||
binding.listView.post { binding.listView.setSelection(0) }
|
||||
binding.listProgressView.isVisible = false
|
||||
binding.filterIcon.isVisible = true
|
||||
binding.listView.isVisible = listData.isNotEmpty()
|
||||
binding.listNoDataView.isVisible = listData.isEmpty()
|
||||
binding.titleCountText.text = LocaleString.resultCount(listData.size)
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
}
|
@@ -53,7 +53,9 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
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.enableAppsConfigsTemplateSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_APP_CONFIG_TEMPLATE)
|
||||
binding.hideIconInLauncherSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_HIDE_ICON)
|
||||
binding.mgrAppsConfigsTemplateButton.isVisible = modulePrefs.get(DataConst.ENABLE_APP_CONFIG_TEMPLATE)
|
||||
binding.hideIconInLauncherSwitch.setOnCheckedChangeListener { btn, b ->
|
||||
if (btn.isPressed.not()) return@setOnCheckedChangeListener
|
||||
modulePrefs.put(DataConst.ENABLE_HIDE_ICON, b)
|
||||
@@ -72,14 +74,15 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
modulePrefs.put(DataConst.ENABLE_ONLY_SHOW_ERRORS_IN_MAIN, b)
|
||||
}
|
||||
binding.enableAppsConfigsTemplateSwitch.setOnCheckedChangeListener { btn, b ->
|
||||
if (b) btn.isChecked = false
|
||||
toastComingSoon()
|
||||
if (btn.isPressed.not()) return@setOnCheckedChangeListener
|
||||
binding.mgrAppsConfigsTemplateButton.isVisible = b
|
||||
modulePrefs.put(DataConst.ENABLE_APP_CONFIG_TEMPLATE, b)
|
||||
}
|
||||
/** 管理应用配置模板按钮点击事件 */
|
||||
binding.mgrAppsConfigsTemplateButton.setOnClickListener { toastComingSoon() }
|
||||
binding.mgrAppsConfigsTemplateButton.setOnClickListener { whenActivated { navigate<ConfigureActivity>() } }
|
||||
/** 功能管理按钮点击事件 */
|
||||
binding.viewErrorsRecordButton.setOnClickListener { navigate<AppErrorsRecordActivity>() }
|
||||
binding.viewMutedErrorsAppsButton.setOnClickListener { navigate<AppErrorsMutedActivity>() }
|
||||
binding.viewErrorsRecordButton.setOnClickListener { whenActivated { navigate<AppErrorsRecordActivity>() } }
|
||||
binding.viewMutedErrorsAppsButton.setOnClickListener { whenActivated { navigate<AppErrorsMutedActivity>() } }
|
||||
/** 重启按钮点击事件 */
|
||||
binding.titleRestartIcon.setOnClickListener { FrameworkTool.restartSystem(context = this) }
|
||||
/** 项目地址按钮点击事件 */
|
||||
@@ -111,8 +114,13 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
binding.mainTextApiWay.text = "Activated by ${YukiHookAPI.Status.executorName} API ${YukiHookAPI.Status.executorVersion}"
|
||||
}
|
||||
|
||||
/** 敬请期待 */
|
||||
private fun toastComingSoon() = toast(msg = "Coming soon")
|
||||
/**
|
||||
* 当模块激活后才能执行相应功能
|
||||
* @param callback 激活后回调
|
||||
*/
|
||||
private inline fun whenActivated(callback: () -> Unit) {
|
||||
if (YukiHookAPI.Status.isXposedModuleActive) callback() else toast(LocaleString.moduleNotActivated)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
@@ -25,6 +25,8 @@ package com.fankes.apperrorstracking.utils.tool
|
||||
|
||||
import android.content.Context
|
||||
import com.fankes.apperrorstracking.bean.AppErrorsInfoBean
|
||||
import com.fankes.apperrorstracking.bean.AppFiltersBean
|
||||
import com.fankes.apperrorstracking.bean.AppInfoBean
|
||||
import com.fankes.apperrorstracking.bean.MutedErrorsAppBean
|
||||
import com.fankes.apperrorstracking.locale.LocaleString
|
||||
import com.fankes.apperrorstracking.utils.factory.execShell
|
||||
@@ -55,7 +57,9 @@ object FrameworkTool {
|
||||
private const val CALL_UNMUTE_ALL_ERRORS_APPS_DATA_RESULT = "call_unmute_all_errors_apps_data_result"
|
||||
|
||||
private val CALL_OPEN_SPECIFY_APP = ChannelData<String>("call_open_specify_app")
|
||||
private val CALL_APP_LIST_DATA_GET = ChannelData<AppFiltersBean>("call_app_info_list_data_get")
|
||||
private val CALL_APP_ERRORS_DATA_REMOVE = ChannelData<AppErrorsInfoBean>("call_app_errors_data_remove")
|
||||
private val CALL_APP_LIST_DATA_GET_RESULT = ChannelData<ArrayList<AppInfoBean>>("call_app_info_list_data_get_result")
|
||||
private val CALL_APP_ERRORS_DATA_GET_RESULT = ChannelData<ArrayList<AppErrorsInfoBean>>("call_app_errors_data_get_result")
|
||||
private val CALL_MUTED_ERRORS_APP_DATA_GET_RESULT = ChannelData<ArrayList<MutedErrorsAppBean>>("call_muted_app_errors_data_get_result")
|
||||
private val CALL_UNMUTE_ERRORS_APP_DATA = ChannelData<MutedErrorsAppBean>("call_unmute_errors_app_data")
|
||||
@@ -177,6 +181,14 @@ object FrameworkTool {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听发送已安装 APP 列表数组
|
||||
* @param result 回调数据
|
||||
*/
|
||||
fun onPushAppListData(result: (AppFiltersBean) -> ArrayList<AppInfoBean>) {
|
||||
instance?.dataChannel?.with { wait(CALL_APP_LIST_DATA_GET) { put(CALL_APP_LIST_DATA_GET_RESULT, result(it)) } }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,4 +326,17 @@ object FrameworkTool {
|
||||
put(CALL_UNMUTE_ALL_ERRORS_APPS_DATA)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取已安装 APP 列表数组
|
||||
* @param context 实例
|
||||
* @param appFilters 过滤条件
|
||||
* @param result 回调数据
|
||||
*/
|
||||
fun fetchAppListData(context: Context, appFilters: AppFiltersBean, result: (ArrayList<AppInfoBean>) -> Unit) {
|
||||
context.dataChannel(SYSTEM_FRAMEWORK_NAME).with {
|
||||
wait(CALL_APP_LIST_DATA_GET_RESULT) { result(it) }
|
||||
put(CALL_APP_LIST_DATA_GET, appFilters)
|
||||
}
|
||||
}
|
||||
}
|
9
app/src/main/res/drawable/ic_filter.xml
Normal file
9
app/src/main/res/drawable/ic_filter.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="184.6dp"
|
||||
android:height="150dp"
|
||||
android:viewportWidth="1260"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M419.2,548.3L17,108.9C-23.6,64.4 13,0 79.7,0h846.5c66.6,0 103.3,64.4 62.8,108.9l-402.2,439.3v472.7c0,1.6 -1.3,2.9 -2.8,2.9a8.3,8.3 0,0 1,-5.2 -1.8l-154.3,-120a13.7,13.7 0,0 1,-5.3 -10.8L419.2,548.3zM838.2,511.9L1257.3,511.9L1257.3,597.2h-419.1L838.2,511.9zM838.2,682.5L1257.3,682.5v85.3h-419.1L838.2,682.5zM838.2,853.2L1257.3,853.2v85.3h-419.1v-85.3z" />
|
||||
</vector>
|
110
app/src/main/res/layout/activity_config.xml
Normal file
110
app/src/main/res/layout/activity_config.xml
Normal file
@@ -0,0 +1,110 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/colorThemeBackground"
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.activity.main.ConfigureActivity"
|
||||
tools:ignore="ContentDescription,UseCompoundDrawables">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:elevation="0dp"
|
||||
android:gravity="center|start"
|
||||
android:paddingLeft="15dp"
|
||||
android:paddingTop="13dp"
|
||||
android:paddingRight="15dp"
|
||||
android:paddingBottom="5dp">
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/title_back_icon"
|
||||
style="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:src="@mipmap/ic_back"
|
||||
android:tint="@color/colorTextGray"
|
||||
android:tooltipText="@string/back" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="2.5dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center|start"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/apps_config_template"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="19sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title_count_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:text="@string/loading"
|
||||
android:textColor="@color/colorTextDark"
|
||||
android:textSize="11.5sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/filter_icon"
|
||||
android:layout_width="22dp"
|
||||
android:layout_height="22dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/ic_filter"
|
||||
android:tint="@color/colorTextGray"
|
||||
android:tooltipText="@string/filter_by_condition"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="10dp"
|
||||
android:animateLayoutChanges="true">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/list_progress_view"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/list_no_data_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:lineSpacingExtra="6dp"
|
||||
android:text="@string/no_list_result"
|
||||
android:textColor="@color/colorTextDark"
|
||||
android:textSize="17sp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<ListView
|
||||
android:id="@+id/list_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:divider="@color/trans"
|
||||
android:dividerHeight="15dp"
|
||||
android:fadingEdgeLength="10dp"
|
||||
android:listSelector="@color/trans"
|
||||
android:paddingLeft="15dp"
|
||||
android:paddingRight="15dp"
|
||||
android:paddingBottom="15dp"
|
||||
android:requiresFadingEdge="vertical"
|
||||
android:scrollbars="none"
|
||||
android:visibility="gone" />
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
@@ -155,6 +155,7 @@
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:fadingEdgeLength="10dp"
|
||||
android:fillViewport="true"
|
||||
@@ -170,37 +171,6 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:background="@drawable/bg_permotion_round"
|
||||
android:elevation="0dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:padding="15dp">
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="15dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:alpha="0.85"
|
||||
android:src="@mipmap/ic_about"
|
||||
android:tint="@color/colorTextDark" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:alpha="0.6"
|
||||
android:lineSpacingExtra="5dp"
|
||||
android:text="@string/after_some_settings_need_restart"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="11sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:animateLayoutChanges="true"
|
||||
android:background="@drawable/bg_permotion_round"
|
||||
|
55
app/src/main/res/layout/adapter_app_info.xml
Normal file
55
app/src/main/res/layout/adapter_app_info.xml
Normal file
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_permotion_ripple"
|
||||
android:gravity="center|start"
|
||||
android:orientation="horizontal"
|
||||
android:padding="10dp"
|
||||
tools:ignore="ContentDescription,UseCompoundDrawables,SmallSp">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="45dp"
|
||||
android:layout_height="45dp"
|
||||
app:cardBackgroundColor="@color/trans"
|
||||
app:cardCornerRadius="10dp"
|
||||
app:cardElevation="0dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/app_icon"
|
||||
android:layout_width="45dp"
|
||||
android:layout_height="45dp" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center|start"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/app_name_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="15sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/config_type_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/colorTextDark"
|
||||
android:textSize="11sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
46
app/src/main/res/layout/dia_app_config.xml
Normal file
46
app/src/main/res/layout/dia_app_config.xml
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="15dp"
|
||||
android:paddingTop="15dp"
|
||||
android:paddingRight="15dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="8.5dp"
|
||||
android:layout_marginRight="8.5dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:lineSpacingExtra="6dp"
|
||||
android:text="@string/when_errors_how_to_show_tip"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<RadioGroup
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<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_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"
|
||||
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_nothing"
|
||||
app:buttonTint="@color/colorPrimaryAccent" />
|
||||
</RadioGroup>
|
||||
</LinearLayout>
|
31
app/src/main/res/layout/dia_apps_filter.xml
Normal file
31
app/src/main/res/layout/dia_apps_filter.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="15dp"
|
||||
android:paddingTop="15dp"
|
||||
android:paddingRight="15dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/app_filters_edit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:hint="@string/typo_app_name_pkg_name"
|
||||
android:singleLine="true" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.checkbox.MaterialCheckBox
|
||||
android:id="@+id/contains_system_switch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/result_contains_system_apps"
|
||||
app:buttonTint="@color/colorPrimaryAccent" />
|
||||
</LinearLayout>
|
@@ -52,7 +52,6 @@
|
||||
<string name="module_version">モジュールバージョン: %1$s</string>
|
||||
<string name="system_version">システムバージョン: %1$s</string>
|
||||
<string name="module_is_activated">モジュールが有効化でした</string>
|
||||
<string name="after_some_settings_need_restart">一部の設定を変更した後、リスタートシステムして有効にするには、右上隅をクリックする必要がある場合があります。</string>
|
||||
<string name="display_settings">表示設定</string>
|
||||
<string name="hide_app_icon_on_launcher">デスクトップ上のアプリアイコンを非表示</string>
|
||||
<string name="hide_app_icon_on_launcher_tip">モジュールアイコンを非表示にすると、インターフェイスが閉じてデスクトップに表示されなくなります。モジュール設定は、EdXposedまたはLSPosedで検索して開くことができます。</string>
|
||||
@@ -88,4 +87,16 @@
|
||||
<string name="unmute">無視を解除</string>
|
||||
<string name="unmute_all">無視を全部解除</string>
|
||||
<string name="are_you_sure_unmute_all">エラーを無視したすべてのアプリを解除してもよろしいですか</string>
|
||||
<string name="apps_config_template">アプリ設定テンプレート</string>
|
||||
<string name="filter_by_condition">条件でフィルタリング</string>
|
||||
<string name="no_list_result">表示結果はありません</string>
|
||||
<string name="typo_app_name_pkg_name">アプリ名とパッケージ名を入力できます</string>
|
||||
<string name="result_contains_system_apps">結果にはシステムアプリが含まれます</string>
|
||||
<string name="clear_filters">条件をクリア</string>
|
||||
<string name="result_count">%1$s の合計結果</string>
|
||||
<string name="loading">ロード中</string>
|
||||
<string name="when_errors_how_to_show_tip">エラーが現在適用されているときにシステムがエラーを表示する方法を構成できます。</string>
|
||||
<string name="show_errors_dialog">エラーダイアログを表示</string>
|
||||
<string name="show_errors_toast">エラー Toast を表示</string>
|
||||
<string name="show_nothing">何も表示されません</string>
|
||||
</resources>
|
@@ -52,7 +52,6 @@
|
||||
<string name="module_version">模块版本:%1$s</string>
|
||||
<string name="system_version">系统版本:%1$s</string>
|
||||
<string name="module_is_activated">模块已激活</string>
|
||||
<string name="after_some_settings_need_restart">部分设置修改后可能需要点击右上角重启系统才能生效。</string>
|
||||
<string name="display_settings">显示设置</string>
|
||||
<string name="hide_app_icon_on_launcher">在桌面隐藏模块图标</string>
|
||||
<string name="hide_app_icon_on_launcher_tip">隐藏模块图标后界面可能会被关闭,将不会再在桌面显示,你可以在 EdXposed、LSPosed 中找到模块设置并打开。</string>
|
||||
@@ -73,19 +72,31 @@
|
||||
<string name="share_error_stack">分享异常堆栈</string>
|
||||
<string name="preference_settings">偏好设置</string>
|
||||
<string name="function_mgr">功能管理</string>
|
||||
<string name="only_show_errors_in_front">仅对前台应用展示错误对话框</string>
|
||||
<string name="only_show_errors_in_main_process">仅对应用主进程展示错误对话框</string>
|
||||
<string name="only_show_errors_in_front">仅对前台应用显示错误对话框</string>
|
||||
<string name="only_show_errors_in_main_process">仅对应用主进程显示错误对话框</string>
|
||||
<string name="enable_apps_config_template">启用应用配置模板</string>
|
||||
<string name="mgr_apps_config_template">管理应用配置模板</string>
|
||||
<string name="view_errors_record">查看异常历史记录</string>
|
||||
<string name="view_muted_errors_apps">查看已忽略异常的应用</string>
|
||||
<string name="only_show_errors_in_front_tip">启用后,只有发生异常的应用处于前台(正在使用中)时才会展示错误对话框,发生异常的后台应用虽然不会展示错误对话框,但是它们都会被记录到异常历史记录中。</string>
|
||||
<string name="only_show_errors_in_main_process_tip">启用后,只有应用发生的异常位于主进程(第一个 Application 实例对象)时才会展示错误对话框。</string>
|
||||
<string name="apps_config_template_tip">你可以在这里对每个应用发生异常时,单独配置其在发生异常时是否展示错误对话框。</string>
|
||||
<string name="only_show_errors_in_front_tip">启用后,只有发生异常的应用处于前台(正在使用中)时才会显示错误对话框,发生异常的后台应用虽然不会显示错误对话框,但是它们都会被记录到异常历史记录中。</string>
|
||||
<string name="only_show_errors_in_main_process_tip">启用后,只有应用发生的异常位于主进程(第一个 Application 实例对象)时才会显示错误对话框。</string>
|
||||
<string name="apps_config_template_tip">你可以在这里对每个应用发生异常时,单独配置其在发生异常时是否显示错误对话框。</string>
|
||||
<string name="view_errors_record_tip">在这里,你可以找到从系统开机以来到现在为止的全部应用异常记录,异常历史记录在重新启动后会自动清空,你可以对记录进行查看、导出和分享以及清空。</string>
|
||||
<string name="view_muted_errors_apps_tip">在这里,你可以找到已被你以不同形式手动忽略异常的应用,这个列表将会在重新启动后自动清空,你可以对这些已忽略的应用进行管理以及从忽略列表中移除它们。</string>
|
||||
<string name="muted_errors_apps">已忽略异常的应用</string>
|
||||
<string name="unmute">取消忽略</string>
|
||||
<string name="unmute_all">取消全部忽略</string>
|
||||
<string name="are_you_sure_unmute_all">你确定要取消全部已忽略异常的应用吗?</string>
|
||||
<string name="apps_config_template">应用配置模板</string>
|
||||
<string name="filter_by_condition">按条件过滤</string>
|
||||
<string name="no_list_result">没有结果可以显示</string>
|
||||
<string name="typo_app_name_pkg_name">可输入 APP 名称、包名</string>
|
||||
<string name="result_contains_system_apps">结果包含系统应用</string>
|
||||
<string name="clear_filters">清除条件</string>
|
||||
<string name="result_count">共 %1$s 个结果</string>
|
||||
<string name="loading">加载中</string>
|
||||
<string name="when_errors_how_to_show_tip">你可以配置当前应用崩溃时系统将如何向你显示错误提示信息。</string>
|
||||
<string name="show_errors_dialog">显示错误对话框</string>
|
||||
<string name="show_errors_toast">显示错误 Toast 提示</string>
|
||||
<string name="show_nothing">不显示任何提示</string>
|
||||
</resources>
|
@@ -52,7 +52,6 @@
|
||||
<string name="module_version">模組版本:%1$s</string>
|
||||
<string name="system_version">系統版本:%1$s</string>
|
||||
<string name="module_is_activated">模組已激活</string>
|
||||
<string name="after_some_settings_need_restart">部分設置修改後可能需要點擊右上角重啟系統才能生效。</string>
|
||||
<string name="display_settings">顯示設置</string>
|
||||
<string name="hide_app_icon_on_launcher">在桌面隱藏模組圖標</string>
|
||||
<string name="hide_app_icon_on_launcher_tip">隱藏模組圖標後界面可能會被關閉,將不會再在桌面顯示,你可以在 EdXposed、LSPosed 中找到模組設置並打開。</string>
|
||||
@@ -88,4 +87,16 @@
|
||||
<string name="unmute">取消忽略</string>
|
||||
<string name="unmute_all">取消全部忽略</string>
|
||||
<string name="are_you_sure_unmute_all">你確認要取消全部已忽略異常的程式嗎?</string>
|
||||
<string name="apps_config_template">程式配置模板</string>
|
||||
<string name="filter_by_condition">按條件過濾</string>
|
||||
<string name="no_list_result">沒有結果可以展示</string>
|
||||
<string name="typo_app_name_pkg_name">可輸入 APP 名稱、包名</string>
|
||||
<string name="result_contains_system_apps">結果包含系統程式</string>
|
||||
<string name="clear_filters">清除條件</string>
|
||||
<string name="result_count">共 %1$s 個結果</string>
|
||||
<string name="loading">加載中</string>
|
||||
<string name="when_errors_how_to_show_tip">你可以配置當前程式崩潰時系統將如何向你展示錯誤提醒副案。</string>
|
||||
<string name="show_errors_dialog">顯示錯誤對話框</string>
|
||||
<string name="show_errors_toast">顯示錯誤 Toast 提示</string>
|
||||
<string name="show_nothing">不顯示任何提示</string>
|
||||
</resources>
|
@@ -52,7 +52,6 @@
|
||||
<string name="module_version">模組版本:%1$s</string>
|
||||
<string name="system_version">系統版本:%1$s</string>
|
||||
<string name="module_is_activated">模組已激活</string>
|
||||
<string name="after_some_settings_need_restart">部分設置修改後可能需要點擊右上角重啟系統才能生效。</string>
|
||||
<string name="display_settings">顯示設置</string>
|
||||
<string name="hide_app_icon_on_launcher">在桌面隱藏模組圖標</string>
|
||||
<string name="hide_app_icon_on_launcher_tip">隱藏模組圖標後界面可能會被關閉,將不會再在桌面顯示,你可以在 EdXposed、LSPosed 中找到模組設置並打開。</string>
|
||||
@@ -88,4 +87,16 @@
|
||||
<string name="unmute">取消忽略</string>
|
||||
<string name="unmute_all">取消全部忽略</string>
|
||||
<string name="are_you_sure_unmute_all">你確認要取消全部已忽略異常的程式嗎?</string>
|
||||
<string name="apps_config_template">程式配置模板</string>
|
||||
<string name="filter_by_condition">按條件過濾</string>
|
||||
<string name="no_list_result">沒有結果可以展示</string>
|
||||
<string name="typo_app_name_pkg_name">可輸入 APP 名稱、包名</string>
|
||||
<string name="result_contains_system_apps">結果包含系統程式</string>
|
||||
<string name="clear_filters">清除條件</string>
|
||||
<string name="result_count">共 %1$s 個結果</string>
|
||||
<string name="loading">加載中</string>
|
||||
<string name="when_errors_how_to_show_tip">你可以配置當前程式崩潰時系統將如何向你展示錯誤提醒副案。</string>
|
||||
<string name="show_errors_dialog">顯示錯誤對話框</string>
|
||||
<string name="show_errors_toast">顯示錯誤 Toast 提示</string>
|
||||
<string name="show_nothing">不顯示任何提示</string>
|
||||
</resources>
|
@@ -52,7 +52,6 @@
|
||||
<string name="module_version">模組版本:%1$s</string>
|
||||
<string name="system_version">系統版本:%1$s</string>
|
||||
<string name="module_is_activated">模組已激活</string>
|
||||
<string name="after_some_settings_need_restart">部分設置修改後可能需要點擊右上角重啟系統才能生效。</string>
|
||||
<string name="display_settings">顯示設置</string>
|
||||
<string name="hide_app_icon_on_launcher">在桌面隱藏模組圖標</string>
|
||||
<string name="hide_app_icon_on_launcher_tip">隱藏模組圖標後界面可能會被關閉,將不會再在桌面顯示,你可以在 EdXposed、LSPosed 中找到模組設置並打開。</string>
|
||||
@@ -88,4 +87,16 @@
|
||||
<string name="unmute">取消忽略</string>
|
||||
<string name="unmute_all">取消全部忽略</string>
|
||||
<string name="are_you_sure_unmute_all">你確認要取消全部已忽略異常的程式嗎?</string>
|
||||
<string name="apps_config_template">程式配置模板</string>
|
||||
<string name="filter_by_condition">按條件過濾</string>
|
||||
<string name="no_list_result">沒有結果可以展示</string>
|
||||
<string name="typo_app_name_pkg_name">可輸入 APP 名稱、包名</string>
|
||||
<string name="result_contains_system_apps">結果包含系統程式</string>
|
||||
<string name="clear_filters">清除條件</string>
|
||||
<string name="result_count">共 %1$s 個結果</string>
|
||||
<string name="loading">加載中</string>
|
||||
<string name="when_errors_how_to_show_tip">你可以配置當前程式崩潰時系統將如何向你展示錯誤提醒副案。</string>
|
||||
<string name="show_errors_dialog">顯示錯誤對話框</string>
|
||||
<string name="show_errors_toast">顯示錯誤 Toast 提示</string>
|
||||
<string name="show_nothing">不顯示任何提示</string>
|
||||
</resources>
|
@@ -52,7 +52,6 @@
|
||||
<string name="module_version">Module version: %1$s</string>
|
||||
<string name="system_version">System version: %1$s</string>
|
||||
<string name="module_is_activated">Module is activated</string>
|
||||
<string name="after_some_settings_need_restart">After some settings are modified, you may need to click the upper right corner to restart the system to take effect.</string>
|
||||
<string name="display_settings">Display settings</string>
|
||||
<string name="hide_app_icon_on_launcher">Hide app icons on launcher</string>
|
||||
<string name="hide_app_icon_on_launcher_tip">After hiding the app icon, the interface may be closed and will no longer be displayed on the launcher. You can find and open the module settings in EdXposed or LSPosed.</string>
|
||||
@@ -88,4 +87,16 @@
|
||||
<string name="unmute">Unmute</string>
|
||||
<string name="unmute_all">Unmute all</string>
|
||||
<string name="are_you_sure_unmute_all">Are you sure you want to unmute all apps?</string>
|
||||
<string name="apps_config_template">Apps Config Template</string>
|
||||
<string name="filter_by_condition">Filter by condition</string>
|
||||
<string name="no_list_result">No result to display</string>
|
||||
<string name="typo_app_name_pkg_name">Typo apps name or package name</string>
|
||||
<string name="result_contains_system_apps">Result contains system apps</string>
|
||||
<string name="clear_filters">Clear filters</string>
|
||||
<string name="result_count">%1$s results found</string>
|
||||
<string name="loading">Loading</string>
|
||||
<string name="when_errors_how_to_show_tip">You can configure how the system will show you errors when the current app crashes.</string>
|
||||
<string name="show_errors_dialog">Show errors dialog</string>
|
||||
<string name="show_errors_toast">Show errors Toast</string>
|
||||
<string name="show_nothing">Don\'t show anything</string>
|
||||
</resources>
|
Reference in New Issue
Block a user