From 4d5dadae8b3f890a9409686b886e511d888c88b8 Mon Sep 17 00:00:00 2001 From: fankesyooni Date: Sun, 22 Jan 2023 14:51:15 +0800 Subject: [PATCH] Modify make crashed apps info persistence and add more info to stackOutputShareContent, stackOutputFileContent in AppErrorsInfoBean, FrameworkHooker, AppErrorsDetailActivity --- .../bean/AppErrorsInfoBean.kt | 57 ++++++++++++------- .../hook/entity/FrameworkHooker.kt | 10 +++- .../errors/AppErrorsDetailActivity.kt | 4 +- 3 files changed, 47 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/com/fankes/apperrorstracking/bean/AppErrorsInfoBean.kt b/app/src/main/java/com/fankes/apperrorstracking/bean/AppErrorsInfoBean.kt index cbaee0e..84d70a8 100644 --- a/app/src/main/java/com/fankes/apperrorstracking/bean/AppErrorsInfoBean.kt +++ b/app/src/main/java/com/fankes/apperrorstracking/bean/AppErrorsInfoBean.kt @@ -22,10 +22,10 @@ package com.fankes.apperrorstracking.bean import android.app.ApplicationErrorReport +import android.content.Context import android.os.Build import com.fankes.apperrorstracking.locale.LocaleString -import com.fankes.apperrorstracking.utils.factory.difference -import com.fankes.apperrorstracking.utils.factory.toUtcTime +import com.fankes.apperrorstracking.utils.factory.* import com.google.gson.annotations.SerializedName import java.io.Serializable import java.text.SimpleDateFormat @@ -35,7 +35,10 @@ import java.util.* * 应用异常信息 bean * @param pid 进程 ID * @param userId 用户 ID + * @param cpuAbi CPU 架构类型 * @param packageName 包名 + * @param versionName 版本名称 + * @param versionCode 版本号 * @param isNativeCrash 是否为原生层异常 * @param exceptionClassName 异常类名 * @param exceptionMessage 异常信息 @@ -51,8 +54,14 @@ data class AppErrorsInfoBean( var pid: Int = -1, @SerializedName("userId") var userId: Int = -1, + @SerializedName("cpuAbi") + var cpuAbi: String = "", @SerializedName("packageName") var packageName: String = "", + @SerializedName("versionName") + var versionName: String = "", + @SerializedName("versionCode") + var versionCode: Long = -1L, @SerializedName("isNativeCrash") var isNativeCrash: Boolean = false, @SerializedName("exceptionClassName") @@ -77,18 +86,22 @@ data class AppErrorsInfoBean( /** * 从 [ApplicationErrorReport.CrashInfo] 克隆 + * @param context 当前实例 * @param pid APP 进程 ID * @param userId APP 用户 ID * @param packageName APP 包名 * @param crashInfo [ApplicationErrorReport.CrashInfo] * @return [AppErrorsInfoBean] */ - fun clone(pid: Int, userId: Int, packageName: String?, crashInfo: ApplicationErrorReport.CrashInfo?) = + fun clone(context: Context, pid: Int, userId: Int, packageName: String?, crashInfo: ApplicationErrorReport.CrashInfo?) = (crashInfo?.exceptionClassName?.lowercase() == "native crash").let { isNativeCrash -> AppErrorsInfoBean( pid = pid, userId = userId, + cpuAbi = packageName?.let { context.appCpuAbiOf(it) } ?: "", packageName = packageName ?: "unknown", + versionName = packageName?.let { context.appVersionNameOf(it) } ?: "", + versionCode = packageName?.let { context.appVersionCodeOf(it) } ?: -1L, isNativeCrash = isNativeCrash, exceptionClassName = crashInfo?.exceptionClassName ?: "unknown", exceptionMessage = if (isNativeCrash) crashInfo?.stackTrace.let { @@ -119,6 +132,12 @@ data class AppErrorsInfoBean( */ val jsonFileName get() = "${packageName}_${pid}_${timestamp}.json" + /** + * 获取 APP 版本信息与版本号 + * @return [String] + */ + val versionBrand get() = if (versionName.isBlank()) "unknown" else "$versionName($versionCode)" + /** * 获取异常本地化 UTC 时间 * @return [String] @@ -153,18 +172,7 @@ data class AppErrorsInfoBean( val stackOutputShareContent get() = "Generated by AppErrorsTracking\n" + "Project Url: https://github.com/KitsunePie/AppErrorsTracking\n" + - "===============\n" + - "[Device Brand]: ${Build.BRAND}\n" + - "[Device Model]: ${Build.MODEL}\n" + - "[Display]: ${Build.DISPLAY}\n" + - "[Android Version]: ${Build.VERSION.RELEASE}\n" + - "[API Version]: ${Build.VERSION.SDK_INT}\n" + - "[System Locale]: ${Locale.getDefault()}\n" + - "[Package Name]: $packageName\n" + - (if (userId > 0) "[User Id]: $userId\n" else "") + - "[Error Type]: ${if (isNativeCrash) "Native" else "Jvm"}\n" + - "[Crash Time]: $utcTime\n" + - "[Stack Trace]:\n" + stackTrace + "===============\n$environmentInfo" /** * 获取异常堆栈文件模板 @@ -175,15 +183,26 @@ data class AppErrorsInfoBean( " Generated by AppErrorsTracking\n" + " Project Url: https://github.com/KitsunePie/AppErrorsTracking\n" + "================================================================\n" + - "[Device Brand]: ${Build.BRAND}\n" + + environmentInfo + + /** + * 获取运行环境信息 + * @return [String] + */ + private val environmentInfo + get() = "[Device Brand]: ${Build.BRAND}\n" + "[Device Model]: ${Build.MODEL}\n" + "[Display]: ${Build.DISPLAY}\n" + "[Android Version]: ${Build.VERSION.RELEASE}\n" + - "[API Version]: ${Build.VERSION.SDK_INT}\n" + + "[Android API Level]: ${Build.VERSION.SDK_INT}\n" + "[System Locale]: ${Locale.getDefault()}\n" + - "[Package Name]: $packageName\n" + + "[Process ID]: $pid\n" + (if (userId > 0) "[User Id]: $userId\n" else "") + - "[Error Type]: ${if (isNativeCrash) "Native" else "Jvm"}\n" + + "[CPU ABI]: ${cpuAbi.ifBlank { "none" }}\n" + + "[Package Name]: $packageName\n" + + "[Version Name]: ${versionName.ifBlank { "unknown" }}\n" + + "[Version Code]: ${versionCode.takeIf { it != -1L } ?: "unknown"}\n" + + "[Error Type]: ${if (isNativeCrash) "Native" else "JVM"}\n" + "[Crash Time]: $utcTime\n" + "[Stack Trace]:\n" + stackTrace } \ No newline at end of file diff --git a/app/src/main/java/com/fankes/apperrorstracking/hook/entity/FrameworkHooker.kt b/app/src/main/java/com/fankes/apperrorstracking/hook/entity/FrameworkHooker.kt index 4f7ec46..51f074e 100644 --- a/app/src/main/java/com/fankes/apperrorstracking/hook/entity/FrameworkHooker.kt +++ b/app/src/main/java/com/fankes/apperrorstracking/hook/entity/FrameworkHooker.kt @@ -350,10 +350,11 @@ object FrameworkHooker : YukiBaseHooker() { /** * 处理 APP 进程异常数据 + * @param context 当前实例 * @param info 系统错误报告数据实例 */ - private fun AppErrorsProcessData.handleAppErrorsInfo(info: ApplicationErrorReport.CrashInfo?) { - AppErrorsRecordData.add(AppErrorsInfoBean.clone(pid, userId, appInfo?.packageName, info)) + private fun AppErrorsProcessData.handleAppErrorsInfo(context: Context, info: ApplicationErrorReport.CrashInfo?) { + AppErrorsRecordData.add(AppErrorsInfoBean.clone(context, pid, userId, appInfo?.packageName, info)) loggerI(msg = "Received crash application data${if (userId != 0) " --user $userId" else ""} --pid $pid") } @@ -441,10 +442,13 @@ object FrameworkHooker : YukiBaseHooker() { returnType = BooleanType } afterHook { + /** 当前实例 */ + val context = appContext ?: field { name = "mContext" }.get(instance).cast() ?: return@afterHook + /** 当前进程信息 */ val proc = args().first().any() ?: return@afterHook loggerW(msg = "Received but got null ProcessRecord") /** 创建 APP 进程异常数据类 */ - AppErrorsProcessData(instance, proc).handleAppErrorsInfo(args(index = 1).cast()) + AppErrorsProcessData(instance, proc).handleAppErrorsInfo(context, args(index = 1).cast()) } } } diff --git a/app/src/main/java/com/fankes/apperrorstracking/ui/activity/errors/AppErrorsDetailActivity.kt b/app/src/main/java/com/fankes/apperrorstracking/ui/activity/errors/AppErrorsDetailActivity.kt index 8eb8733..398818e 100644 --- a/app/src/main/java/com/fankes/apperrorstracking/ui/activity/errors/AppErrorsDetailActivity.kt +++ b/app/src/main/java/com/fankes/apperrorstracking/ui/activity/errors/AppErrorsDetailActivity.kt @@ -105,10 +105,10 @@ class AppErrorsDetailActivity : BaseActivity() { } binding.appIcon.setImageDrawable(appIconOf(appErrorsInfo.packageName)) binding.appNameText.text = appNameOf(appErrorsInfo.packageName) - binding.appVersionText.text = appVersionBrandOf(appErrorsInfo.packageName) + binding.appVersionText.text = appErrorsInfo.versionBrand binding.appUserIdText.isVisible = appErrorsInfo.userId > 0 binding.appUserIdText.text = LocaleString.userId(appErrorsInfo.userId) - binding.appCpuAbiText.text = appCpuAbiOf(appErrorsInfo.packageName).ifBlank { LocaleString.noCpuAbi } + binding.appCpuAbiText.text = appErrorsInfo.cpuAbi.ifBlank { LocaleString.noCpuAbi } binding.jvmErrorPanel.isGone = appErrorsInfo.isNativeCrash binding.errorTypeIcon.setImageResource(if (appErrorsInfo.isNativeCrash) R.drawable.ic_cpp else R.drawable.ic_java) binding.errorInfoText.text = appErrorsInfo.exceptionMessage