pull/1776/head
kunfei 2 years ago
parent 8cad8fe230
commit 2a2e319b6f
  1. 18
      app/src/main/java/io/legado/app/help/ContentProcessor.kt
  2. 107
      app/src/main/java/io/legado/app/help/CrashHandler.kt
  3. 2
      app/src/main/java/io/legado/app/utils/ContextExtensions.kt
  4. 35
      app/src/main/java/io/legado/app/utils/RegexExtensions.kt

@ -8,6 +8,9 @@ import io.legado.app.data.entities.BookChapter
import io.legado.app.data.entities.ReplaceRule
import io.legado.app.help.config.AppConfig
import io.legado.app.help.config.ReadBookConfig
import io.legado.app.utils.RegexTimeoutException
import io.legado.app.utils.msg
import io.legado.app.utils.replace
import io.legado.app.utils.toastOnUi
import splitties.init.appCtx
import java.lang.ref.WeakReference
@ -134,13 +137,22 @@ class ContentProcessor private constructor(
if (item.pattern.isNotEmpty()) {
kotlin.runCatching {
mContent = if (item.isRegex) {
mContent.replace(item.pattern.toRegex(), item.replacement)
mContent.replace(item.pattern.toRegex(), item.replacement, 1000L)
} else {
mContent.replace(item.pattern, item.replacement)
}
}.onFailure {
AppLog.put("${item.name}替换出错\n${it.localizedMessage}", it)
appCtx.toastOnUi("${item.name}替换出错")
when (it) {
is RegexTimeoutException -> {
item.isEnabled = false
appDb.replaceRuleDao.update(item)
return it.msg
}
else -> {
AppLog.put("${item.name}替换出错\n${it.localizedMessage}", it)
appCtx.toastOnUi("${item.name}替换出错")
}
}
}
}
}

@ -9,6 +9,7 @@ import io.legado.app.utils.FileUtils
import io.legado.app.utils.getFile
import io.legado.app.utils.longToastOnUi
import io.legado.app.utils.msg
import splitties.init.appCtx
import java.io.PrintWriter
import java.io.StringWriter
import java.text.SimpleDateFormat
@ -26,17 +27,6 @@ class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler {
*/
private var mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler()
/**
* 存储异常和参数信息
*/
private val paramsMap = HashMap<String, String>()
/**
* 格式化时间
*/
@SuppressLint("SimpleDateFormat")
private val format = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss")
init {
//设置该CrashHandler为系统默认的
Thread.setDefaultUncaughtExceptionHandler(this)
@ -56,62 +46,71 @@ class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler {
*/
private fun handleException(ex: Throwable?) {
if (ex == null) return
//收集设备参数信息
collectDeviceInfo()
//保存日志文件
saveCrashInfo2File(ex)
context.longToastOnUi(ex.msg)
Thread.sleep(3000)
}
/**
* 收集设备参数信息
*/
private fun collectDeviceInfo() {
kotlin.runCatching {
//获取系统信息
paramsMap["MANUFACTURER"] = Build.MANUFACTURER
paramsMap["BRAND"] = Build.BRAND
//获取app版本信息
AppConst.appInfo.let {
paramsMap["versionName"] = it.versionName
paramsMap["versionCode"] = it.versionCode.toString()
companion object {
/**
* 存储异常和参数信息
*/
private val paramsMap by lazy {
val map = HashMap<String, String>()
kotlin.runCatching {
//获取系统信息
map["MANUFACTURER"] = Build.MANUFACTURER
map["BRAND"] = Build.BRAND
//获取app版本信息
AppConst.appInfo.let {
map["versionName"] = it.versionName
map["versionCode"] = it.versionCode.toString()
}
}
map
}
}
/**
* 保存错误信息到文件中
*/
private fun saveCrashInfo2File(ex: Throwable) {
val sb = StringBuilder()
for ((key, value) in paramsMap) {
sb.append(key).append("=").append(value).append("\n")
}
/**
* 格式化时间
*/
@SuppressLint("SimpleDateFormat")
private val format = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss")
val writer = StringWriter()
val printWriter = PrintWriter(writer)
ex.printStackTrace(printWriter)
var cause: Throwable? = ex.cause
while (cause != null) {
cause.printStackTrace(printWriter)
cause = cause.cause
}
printWriter.close()
val result = writer.toString()
sb.append(result)
val timestamp = System.currentTimeMillis()
val time = format.format(Date())
val fileName = "crash-$time-$timestamp.log"
context.externalCacheDir?.let { rootFile ->
rootFile.getFile("crash").listFiles()?.forEach {
if (it.lastModified() < System.currentTimeMillis() - TimeUnit.DAYS.toMillis(7)) {
it.delete()
/**
* 保存错误信息到文件中
*/
fun saveCrashInfo2File(ex: Throwable) {
val sb = StringBuilder()
for ((key, value) in paramsMap) {
sb.append(key).append("=").append(value).append("\n")
}
val writer = StringWriter()
val printWriter = PrintWriter(writer)
ex.printStackTrace(printWriter)
var cause: Throwable? = ex.cause
while (cause != null) {
cause.printStackTrace(printWriter)
cause = cause.cause
}
printWriter.close()
val result = writer.toString()
sb.append(result)
val timestamp = System.currentTimeMillis()
val time = format.format(Date())
val fileName = "crash-$time-$timestamp.log"
appCtx.externalCacheDir?.let { rootFile ->
rootFile.getFile("crash").listFiles()?.forEach {
if (it.lastModified() < System.currentTimeMillis() - TimeUnit.DAYS.toMillis(7)) {
it.delete()
}
}
FileUtils.createFileIfNotExist(rootFile, "crash", fileName)
.writeText(sb.toString())
}
FileUtils.createFileIfNotExist(rootFile, "crash", fileName)
.writeText(sb.toString())
}
}
}

@ -33,6 +33,7 @@ import splitties.systemservices.clipboardManager
import splitties.systemservices.connectivityManager
import java.io.File
import java.io.FileOutputStream
import kotlin.system.exitProcess
inline fun <reified A : Activity> Context.startActivity(configIntent: Intent.() -> Unit = {}) {
val intent = Intent(this, A::class.java)
@ -168,6 +169,7 @@ fun Context.restart() {
startActivity(intent)
//杀掉以前进程
Process.killProcess(Process.myPid())
exitProcess(0)
}
}

@ -1,10 +1,37 @@
package io.legado.app.utils
import io.legado.app.exception.NoStackTraceException
import io.legado.app.help.CrashHandler
import kotlinx.coroutines.suspendCancellableCoroutine
import splitties.init.appCtx
import kotlin.concurrent.thread
import kotlin.coroutines.resume
suspend fun CharSequence.regexReplace(regex: String, replacement: String, timeout: Long): String {
return suspendCancellableCoroutine {
suspend fun CharSequence.replace(regex: Regex, replacement: String, timeout: Long): String {
return suspendCancellableCoroutine { block ->
val thread = thread {
try {
val result = regex.replace(this, replacement)
block.resume(result)
} catch (e: Exception) {
block.cancel(e)
}
}
mainHandler.postDelayed({
if (thread.isAlive) {
val timeoutMsg = "替换超时,将在3秒后重启应用\n替换规则$regex\n替换内容:${this}"
val exception = RegexTimeoutException(timeoutMsg)
block.cancel(exception)
appCtx.longToastOnUi(timeoutMsg)
CrashHandler.saveCrashInfo2File(exception)
mainHandler.postDelayed({
if (thread.isAlive) {
appCtx.restart()
}
}, 3000)
}
}, timeout)
}
}
class RegexTimeoutException(msg: String) : NoStackTraceException(msg)
Loading…
Cancel
Save