mirror of
https://github.com/KitsunePie/AppErrorsTracking.git
synced 2025-09-01 16:55:18 +08:00
Merge to new DialogBuilder
This commit is contained in:
@@ -19,11 +19,10 @@
|
||||
*
|
||||
* This file is Created by fankes on 2022/5/7.
|
||||
*/
|
||||
@file:Suppress("DEPRECATION", "UseCompatLoadingForDrawables")
|
||||
@file:Suppress("UseCompatLoadingForDrawables")
|
||||
|
||||
package com.fankes.apperrorstracking.hook.entity
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.app.ApplicationErrorReport
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
@@ -36,10 +35,10 @@ import android.text.TextUtils
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import com.fankes.apperrorstracking.R
|
||||
import com.fankes.apperrorstracking.bean.AppErrorsInfoBean
|
||||
import com.fankes.apperrorstracking.locale.LocaleString
|
||||
@@ -77,7 +76,7 @@ object FrameworkHooker : YukiBaseHooker() {
|
||||
)
|
||||
|
||||
/** 已打开的错误对话框数组 */
|
||||
private var openedErrorsDialogs = HashMap<String, AlertDialog>()
|
||||
private var openedErrorsDialogs = HashMap<String, DialogBuilder>()
|
||||
|
||||
/** 已忽略错误的 APP 数组 - 直到重新解锁 */
|
||||
private var ignoredErrorsIfUnlockApps = HashSet<String>()
|
||||
@@ -145,7 +144,7 @@ object FrameworkHooker : YukiBaseHooker() {
|
||||
layoutParams =
|
||||
ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
addView(ImageView(context).apply {
|
||||
setImageDrawable(moduleAppResources.getDrawable(drawableId))
|
||||
setImageDrawable(ResourcesCompat.getDrawable(moduleAppResources, drawableId, null))
|
||||
layoutParams = ViewGroup.LayoutParams(25.dp(context), 25.dp(context))
|
||||
setColorFilter(if (context.isSystemInDarkMode) Color.WHITE else Color.BLACK)
|
||||
})
|
||||
@@ -240,13 +239,9 @@ object FrameworkHooker : YukiBaseHooker() {
|
||||
/** 关闭重复的对话框 */
|
||||
openedErrorsDialogs[packageName]?.cancel()
|
||||
/** 创建自定义对话框 */
|
||||
AlertDialog.Builder(
|
||||
context, if (context.isSystemInDarkMode)
|
||||
android.R.style.Theme_Material_Dialog
|
||||
else android.R.style.Theme_Material_Light_Dialog
|
||||
).create().apply {
|
||||
setTitle(if (isRepeating) LocaleString.aerrRepeatedTitle(appName) else LocaleString.aerrTitle(appName))
|
||||
setView(LinearLayout(context).apply {
|
||||
context.showDialog {
|
||||
title = if (isRepeating) LocaleString.aerrRepeatedTitle(appName) else LocaleString.aerrTitle(appName)
|
||||
view = LinearLayout(context).apply {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
/** 应用信息按钮 */
|
||||
val appInfoButton =
|
||||
@@ -301,14 +296,14 @@ object FrameworkHooker : YukiBaseHooker() {
|
||||
addView(ignoredUntilRestartButton)
|
||||
/** 设置边距 */
|
||||
setPadding(6.dp(context), 15.dp(context), 6.dp(context), 6.dp(context))
|
||||
})
|
||||
/** 只有 SystemUid 才能响应系统级别的对话框 */
|
||||
window?.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
|
||||
}
|
||||
/** 设置取消对话框监听 */
|
||||
onCancel { openedErrorsDialogs.remove(packageName) }
|
||||
/** 记录实例 */
|
||||
openedErrorsDialogs[packageName] = this
|
||||
/** 设置取消对话框监听 */
|
||||
setOnCancelListener { openedErrorsDialogs.remove(packageName) }
|
||||
}.show()
|
||||
/** 只有 SystemUid 才能响应系统级别的对话框 */
|
||||
makeSystemAlert()
|
||||
}
|
||||
}
|
||||
}
|
||||
injectMember {
|
||||
|
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* 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/12.
|
||||
*/
|
||||
@file:Suppress("unused", "OPT_IN_USAGE", "EXPERIMENTAL_API_USAGE", "DEPRECATION")
|
||||
|
||||
package com.fankes.apperrorstracking.utils.factory
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.graphics.drawable.InsetDrawable
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
|
||||
/**
|
||||
* 构造对话框
|
||||
* @param it 对话框方法体
|
||||
*/
|
||||
fun Context.showDialog(it: DialogBuilder.() -> Unit) =
|
||||
DialogBuilder(this).apply(it).show()
|
||||
|
||||
/**
|
||||
* 对话框构造器
|
||||
* @param context 实例
|
||||
*/
|
||||
class DialogBuilder(private val context: Context) {
|
||||
|
||||
private var instanceAndroidX: androidx.appcompat.app.AlertDialog.Builder? = null // 实例对象
|
||||
private var instanceAndroid: android.app.AlertDialog.Builder? = null // 实例对象
|
||||
|
||||
private var isSystemAlert = false // 标识为系统级别的对话框
|
||||
|
||||
private var onCancel: (() -> Unit)? = null // 对话框取消监听
|
||||
|
||||
private var dialogInstance: Dialog? = null // 对话框实例
|
||||
|
||||
private var customLayoutView: View? = null // 自定义布局
|
||||
|
||||
/**
|
||||
* 是否需要使用 AndroidX 风格对话框
|
||||
* @return [Boolean]
|
||||
*/
|
||||
private val isUsingAndroidX get() = runCatching { context is AppCompatActivity }.getOrNull() ?: false
|
||||
|
||||
init {
|
||||
if (isUsingAndroidX)
|
||||
runCatching { instanceAndroidX = MaterialAlertDialogBuilder(context) }
|
||||
else runCatching {
|
||||
instanceAndroid = android.app.AlertDialog.Builder(
|
||||
context,
|
||||
if (context.isSystemInDarkMode) android.R.style.Theme_Material_Dialog else android.R.style.Theme_Material_Light_Dialog
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** 设置对话框不可关闭 */
|
||||
fun noCancelable() {
|
||||
if (isUsingAndroidX)
|
||||
runCatching { instanceAndroidX?.setCancelable(false) }
|
||||
else runCatching { instanceAndroid?.setCancelable(false) }
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置为系统级别对话框
|
||||
*
|
||||
* - ❗仅可在系统级别的 APP 中生效
|
||||
*/
|
||||
fun makeSystemAlert() {
|
||||
isSystemAlert = true
|
||||
}
|
||||
|
||||
/** 设置对话框标题 */
|
||||
var title
|
||||
get() = ""
|
||||
set(value) {
|
||||
if (isUsingAndroidX)
|
||||
runCatching { instanceAndroidX?.setTitle(value) }
|
||||
else runCatching { instanceAndroid?.setTitle(value) }
|
||||
}
|
||||
|
||||
/** 设置对话框消息内容 */
|
||||
var msg
|
||||
get() = ""
|
||||
set(value) {
|
||||
if (isUsingAndroidX)
|
||||
runCatching { instanceAndroidX?.setMessage(value) }
|
||||
else runCatching { instanceAndroid?.setMessage(value) }
|
||||
}
|
||||
|
||||
/** 设置进度条对话框消息内容 */
|
||||
var progressContent
|
||||
get() = ""
|
||||
set(value) {
|
||||
if (customLayoutView == null)
|
||||
customLayoutView = LinearLayout(context).apply {
|
||||
orientation = LinearLayout.HORIZONTAL
|
||||
gravity = Gravity.CENTER or Gravity.START
|
||||
addView(ProgressBar(context))
|
||||
addView(View(context).apply { layoutParams = ViewGroup.LayoutParams(20.dp(context), 5) })
|
||||
addView(TextView(context).apply {
|
||||
tag = "progressContent"
|
||||
text = value
|
||||
})
|
||||
setPadding(20.dp(context), 20.dp(context), 20.dp(context), 20.dp(context))
|
||||
}
|
||||
else customLayoutView?.findViewWithTag<TextView>("progressContent")?.text = value
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置对话框自定义布局
|
||||
* @return [customLayoutView]
|
||||
*/
|
||||
var view
|
||||
get() = customLayoutView
|
||||
set(value) {
|
||||
customLayoutView = value
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置对话框确定按钮
|
||||
* @param text 按钮文本内容
|
||||
* @param it 点击事件
|
||||
*/
|
||||
fun confirmButton(text: String = "确定", it: () -> Unit = {}) {
|
||||
if (isUsingAndroidX)
|
||||
runCatching { instanceAndroidX?.setPositiveButton(text) { _, _ -> it() } }
|
||||
else runCatching { instanceAndroid?.setPositiveButton(text) { _, _ -> it() } }
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置对话框取消按钮
|
||||
* @param text 按钮文本内容
|
||||
* @param it 点击事件
|
||||
*/
|
||||
fun cancelButton(text: String = "取消", it: () -> Unit = {}) {
|
||||
if (isUsingAndroidX)
|
||||
runCatching { instanceAndroidX?.setNegativeButton(text) { _, _ -> it() } }
|
||||
else runCatching { instanceAndroid?.setNegativeButton(text) { _, _ -> it() } }
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置对话框第三个按钮
|
||||
* @param text 按钮文本内容
|
||||
* @param it 点击事件
|
||||
*/
|
||||
fun neutralButton(text: String = "更多", it: () -> Unit = {}) {
|
||||
if (isUsingAndroidX)
|
||||
runCatching { instanceAndroidX?.setNeutralButton(text) { _, _ -> it() } }
|
||||
else runCatching { instanceAndroid?.setNeutralButton(text) { _, _ -> it() } }
|
||||
}
|
||||
|
||||
/**
|
||||
* 当对话框关闭时
|
||||
* @param it 回调
|
||||
*/
|
||||
fun onCancel(it: () -> Unit) {
|
||||
onCancel = it
|
||||
}
|
||||
|
||||
/** 取消对话框 */
|
||||
fun cancel() = dialogInstance?.cancel()
|
||||
|
||||
/** 显示对话框 */
|
||||
internal fun show() {
|
||||
if (isUsingAndroidX) runCatching {
|
||||
instanceAndroidX?.create()?.apply {
|
||||
customLayoutView?.let { setView(it) }
|
||||
dialogInstance = this
|
||||
setOnCancelListener { onCancel?.invoke() }
|
||||
/** 只有 SystemUid 才能响应系统级别的对话框 */
|
||||
if (isSystemAlert) runCatching { window?.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT) }
|
||||
}?.show()
|
||||
} else runCatching {
|
||||
instanceAndroid?.create()?.apply {
|
||||
customLayoutView?.let { setView(it) }
|
||||
window?.attributes
|
||||
window?.setBackgroundDrawable(
|
||||
InsetDrawable(
|
||||
GradientDrawable(
|
||||
GradientDrawable.Orientation.TOP_BOTTOM,
|
||||
if (context.isSystemInDarkMode) intArrayOf(0xFF2D2D2D.toInt(), 0xFF2D2D2D.toInt())
|
||||
else intArrayOf(Color.WHITE, Color.WHITE)
|
||||
).apply {
|
||||
shape = GradientDrawable.RECTANGLE
|
||||
gradientType = GradientDrawable.LINEAR_GRADIENT
|
||||
cornerRadius = 15.dpFloat(this@DialogBuilder.context)
|
||||
}, 30.dp(context), 0, 30.dp(context), 0
|
||||
)
|
||||
)
|
||||
dialogInstance = this
|
||||
setOnCancelListener { onCancel?.invoke() }
|
||||
/** 只有 SystemUid 才能响应系统级别的对话框 */
|
||||
if (isSystemAlert) runCatching { window?.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT) }
|
||||
}?.show()
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user