|
@@ -1,11 +1,13 @@
|
|
|
package io.legado.app.help
|
|
package io.legado.app.help
|
|
|
|
|
|
|
|
import android.annotation.SuppressLint
|
|
import android.annotation.SuppressLint
|
|
|
|
|
+import android.content.Intent
|
|
|
import android.content.Context
|
|
import android.content.Context
|
|
|
import android.net.Uri
|
|
import android.net.Uri
|
|
|
import android.os.Build
|
|
import android.os.Build
|
|
|
import android.os.Debug
|
|
import android.os.Debug
|
|
|
import android.os.Looper
|
|
import android.os.Looper
|
|
|
|
|
+import android.os.Process
|
|
|
import android.webkit.WebSettings
|
|
import android.webkit.WebSettings
|
|
|
import io.legado.app.constant.AppConst
|
|
import io.legado.app.constant.AppConst
|
|
|
import io.legado.app.constant.AppLog
|
|
import io.legado.app.constant.AppLog
|
|
@@ -28,6 +30,7 @@ import java.io.StringWriter
|
|
|
import java.text.SimpleDateFormat
|
|
import java.text.SimpleDateFormat
|
|
|
import java.util.Date
|
|
import java.util.Date
|
|
|
import java.util.concurrent.TimeUnit
|
|
import java.util.concurrent.TimeUnit
|
|
|
|
|
+import kotlin.system.exitProcess
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 异常管理类
|
|
* 异常管理类
|
|
@@ -53,8 +56,12 @@ class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler {
|
|
|
Looper.loop()
|
|
Looper.loop()
|
|
|
} else {
|
|
} else {
|
|
|
ReadAloud.stop(context)
|
|
ReadAloud.stop(context)
|
|
|
- handleException(ex)
|
|
|
|
|
- mDefaultHandler?.uncaughtException(thread, ex)
|
|
|
|
|
|
|
+ if (handleException(ex)) {
|
|
|
|
|
+ Process.killProcess(Process.myPid())
|
|
|
|
|
+ exitProcess(10)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ mDefaultHandler?.uncaughtException(thread, ex)
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -73,19 +80,39 @@ class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler {
|
|
|
/**
|
|
/**
|
|
|
* 处理该异常
|
|
* 处理该异常
|
|
|
*/
|
|
*/
|
|
|
- private fun handleException(ex: Throwable?) {
|
|
|
|
|
- if (ex == null) return
|
|
|
|
|
|
|
+ private fun handleException(ex: Throwable?): Boolean {
|
|
|
|
|
+ if (ex == null) return false
|
|
|
LocalConfig.appCrash = true
|
|
LocalConfig.appCrash = true
|
|
|
//保存日志文件
|
|
//保存日志文件
|
|
|
- saveCrashInfo2File(ex)
|
|
|
|
|
|
|
+ val crashFileName = saveCrashInfo2File(ex)
|
|
|
if ((ex is OutOfMemoryError || ex.cause is OutOfMemoryError) && AppConfig.recordHeapDump) {
|
|
if ((ex is OutOfMemoryError || ex.cause is OutOfMemoryError) && AppConfig.recordHeapDump) {
|
|
|
doHeapDump()
|
|
doHeapDump()
|
|
|
}
|
|
}
|
|
|
- context.longToastOnUiLegacy(ex.stackTraceStr)
|
|
|
|
|
- Thread.sleep(3000)
|
|
|
|
|
|
|
+ return if (startCrashReport(crashFileName)) {
|
|
|
|
|
+ LocalConfig.appCrash = false
|
|
|
|
|
+ true
|
|
|
|
|
+ } else {
|
|
|
|
|
+ context.longToastOnUiLegacy(ex.stackTraceStr)
|
|
|
|
|
+ Thread.sleep(3000)
|
|
|
|
|
+ false
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private fun startCrashReport(fileName: String): Boolean {
|
|
|
|
|
+ return runCatching {
|
|
|
|
|
+ val intent = Intent()
|
|
|
|
|
+ .setClassName(context.packageName, CRASH_REPORT_ACTIVITY)
|
|
|
|
|
+ .putExtra(EXTRA_CRASH_FILE_NAME, fileName)
|
|
|
|
|
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
|
|
|
|
+ context.startActivity(intent)
|
|
|
|
|
+ }.isSuccess
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
companion object {
|
|
companion object {
|
|
|
|
|
+ const val EXTRA_CRASH_FILE_NAME = "crashFileName"
|
|
|
|
|
+
|
|
|
|
|
+ private const val CRASH_REPORT_ACTIVITY = "io.legado.app.ui.about.CrashReportActivity"
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 存储异常和参数信息
|
|
* 存储异常和参数信息
|
|
|
*/
|
|
*/
|
|
@@ -123,7 +150,7 @@ class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler {
|
|
|
/**
|
|
/**
|
|
|
* 保存错误信息到文件中
|
|
* 保存错误信息到文件中
|
|
|
*/
|
|
*/
|
|
|
- fun saveCrashInfo2File(ex: Throwable) {
|
|
|
|
|
|
|
+ fun saveCrashInfo2File(ex: Throwable): String {
|
|
|
val sb = StringBuilder()
|
|
val sb = StringBuilder()
|
|
|
for ((key, value) in paramsMap) {
|
|
for ((key, value) in paramsMap) {
|
|
|
sb.append(key).append("=").append(value).append("\n")
|
|
sb.append(key).append("=").append(value).append("\n")
|
|
@@ -165,6 +192,19 @@ class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler {
|
|
|
.writeText(crashLog)
|
|
.writeText(crashLog)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ return fileName
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ fun readCrashLog(fileName: String?): String? {
|
|
|
|
|
+ return runCatching {
|
|
|
|
|
+ val crashDir = appCtx.externalCacheDir?.resolve("crash") ?: return null
|
|
|
|
|
+ val file = fileName
|
|
|
|
|
+ ?.let { crashDir.resolve(it) }
|
|
|
|
|
+ ?.takeIf { it.isFile }
|
|
|
|
|
+ ?: crashDir.listFiles { file -> file.isFile }
|
|
|
|
|
+ ?.maxByOrNull { it.name }
|
|
|
|
|
+ file?.readText()
|
|
|
|
|
+ }.getOrNull()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|