Merge to new DialogBuilder

This commit is contained in:
2022-05-12 02:35:48 +08:00
parent 4988ebbf3b
commit 13b23ad59c
2 changed files with 236 additions and 18 deletions

View File

@@ -19,11 +19,10 @@
* *
* This file is Created by fankes on 2022/5/7. * This file is Created by fankes on 2022/5/7.
*/ */
@file:Suppress("DEPRECATION", "UseCompatLoadingForDrawables") @file:Suppress("UseCompatLoadingForDrawables")
package com.fankes.apperrorstracking.hook.entity package com.fankes.apperrorstracking.hook.entity
import android.app.AlertDialog
import android.app.ApplicationErrorReport import android.app.ApplicationErrorReport
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
@@ -36,10 +35,10 @@ import android.text.TextUtils
import android.view.Gravity import android.view.Gravity
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.WindowManager
import android.widget.ImageView import android.widget.ImageView
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import androidx.core.content.res.ResourcesCompat
import com.fankes.apperrorstracking.R import com.fankes.apperrorstracking.R
import com.fankes.apperrorstracking.bean.AppErrorsInfoBean import com.fankes.apperrorstracking.bean.AppErrorsInfoBean
import com.fankes.apperrorstracking.locale.LocaleString 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 数组 - 直到重新解锁 */ /** 已忽略错误的 APP 数组 - 直到重新解锁 */
private var ignoredErrorsIfUnlockApps = HashSet<String>() private var ignoredErrorsIfUnlockApps = HashSet<String>()
@@ -145,7 +144,7 @@ object FrameworkHooker : YukiBaseHooker() {
layoutParams = layoutParams =
ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
addView(ImageView(context).apply { addView(ImageView(context).apply {
setImageDrawable(moduleAppResources.getDrawable(drawableId)) setImageDrawable(ResourcesCompat.getDrawable(moduleAppResources, drawableId, null))
layoutParams = ViewGroup.LayoutParams(25.dp(context), 25.dp(context)) layoutParams = ViewGroup.LayoutParams(25.dp(context), 25.dp(context))
setColorFilter(if (context.isSystemInDarkMode) Color.WHITE else Color.BLACK) setColorFilter(if (context.isSystemInDarkMode) Color.WHITE else Color.BLACK)
}) })
@@ -240,13 +239,9 @@ object FrameworkHooker : YukiBaseHooker() {
/** 关闭重复的对话框 */ /** 关闭重复的对话框 */
openedErrorsDialogs[packageName]?.cancel() openedErrorsDialogs[packageName]?.cancel()
/** 创建自定义对话框 */ /** 创建自定义对话框 */
AlertDialog.Builder( context.showDialog {
context, if (context.isSystemInDarkMode) title = if (isRepeating) LocaleString.aerrRepeatedTitle(appName) else LocaleString.aerrTitle(appName)
android.R.style.Theme_Material_Dialog view = LinearLayout(context).apply {
else android.R.style.Theme_Material_Light_Dialog
).create().apply {
setTitle(if (isRepeating) LocaleString.aerrRepeatedTitle(appName) else LocaleString.aerrTitle(appName))
setView(LinearLayout(context).apply {
orientation = LinearLayout.VERTICAL orientation = LinearLayout.VERTICAL
/** 应用信息按钮 */ /** 应用信息按钮 */
val appInfoButton = val appInfoButton =
@@ -301,14 +296,14 @@ object FrameworkHooker : YukiBaseHooker() {
addView(ignoredUntilRestartButton) addView(ignoredUntilRestartButton)
/** 设置边距 */ /** 设置边距 */
setPadding(6.dp(context), 15.dp(context), 6.dp(context), 6.dp(context)) 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 openedErrorsDialogs[packageName] = this
/** 设置取消对话框监听 */ /** 只有 SystemUid 才能响应系统级别的对话框 */
setOnCancelListener { openedErrorsDialogs.remove(packageName) } makeSystemAlert()
}.show() }
} }
} }
injectMember { injectMember {

View File

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