kunfei 4 vuotta sitten
vanhempi
commit
9a3403bc9a

+ 15 - 3
app/src/main/java/io/legado/app/help/ContentProcessor.kt

@@ -8,6 +8,9 @@ import io.legado.app.data.entities.BookChapter
 import io.legado.app.data.entities.ReplaceRule
 import io.legado.app.data.entities.ReplaceRule
 import io.legado.app.help.config.AppConfig
 import io.legado.app.help.config.AppConfig
 import io.legado.app.help.config.ReadBookConfig
 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 io.legado.app.utils.toastOnUi
 import splitties.init.appCtx
 import splitties.init.appCtx
 import java.lang.ref.WeakReference
 import java.lang.ref.WeakReference
@@ -134,13 +137,22 @@ class ContentProcessor private constructor(
             if (item.pattern.isNotEmpty()) {
             if (item.pattern.isNotEmpty()) {
                 kotlin.runCatching {
                 kotlin.runCatching {
                     mContent = if (item.isRegex) {
                     mContent = if (item.isRegex) {
-                        mContent.replace(item.pattern.toRegex(), item.replacement)
+                        mContent.replace(item.pattern.toRegex(), item.replacement, 1000L)
                     } else {
                     } else {
                         mContent.replace(item.pattern, item.replacement)
                         mContent.replace(item.pattern, item.replacement)
                     }
                     }
                 }.onFailure {
                 }.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}替换出错")
+                        }
+                    }
                 }
                 }
             }
             }
         }
         }

+ 53 - 54
app/src/main/java/io/legado/app/help/CrashHandler.kt

@@ -9,6 +9,7 @@ import io.legado.app.utils.FileUtils
 import io.legado.app.utils.getFile
 import io.legado.app.utils.getFile
 import io.legado.app.utils.longToastOnUi
 import io.legado.app.utils.longToastOnUi
 import io.legado.app.utils.msg
 import io.legado.app.utils.msg
+import splitties.init.appCtx
 import java.io.PrintWriter
 import java.io.PrintWriter
 import java.io.StringWriter
 import java.io.StringWriter
 import java.text.SimpleDateFormat
 import java.text.SimpleDateFormat
@@ -26,17 +27,6 @@ class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler {
      */
      */
     private var mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler()
     private var mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler()
 
 
-    /**
-     * 存储异常和参数信息
-     */
-    private val paramsMap = HashMap<String, String>()
-
-    /**
-     * 格式化时间
-     */
-    @SuppressLint("SimpleDateFormat")
-    private val format = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss")
-
     init {
     init {
         //设置该CrashHandler为系统默认的
         //设置该CrashHandler为系统默认的
         Thread.setDefaultUncaughtExceptionHandler(this)
         Thread.setDefaultUncaughtExceptionHandler(this)
@@ -56,62 +46,71 @@ class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler {
      */
      */
     private fun handleException(ex: Throwable?) {
     private fun handleException(ex: Throwable?) {
         if (ex == null) return
         if (ex == null) return
-        //收集设备参数信息
-        collectDeviceInfo()
         //保存日志文件
         //保存日志文件
         saveCrashInfo2File(ex)
         saveCrashInfo2File(ex)
         context.longToastOnUi(ex.msg)
         context.longToastOnUi(ex.msg)
         Thread.sleep(3000)
         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())
         }
         }
+
     }
     }
 
 
 }
 }

+ 2 - 0
app/src/main/java/io/legado/app/utils/ContextExtensions.kt

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

+ 31 - 4
app/src/main/java/io/legado/app/utils/RegexExtensions.kt

@@ -1,10 +1,37 @@
 package io.legado.app.utils
 package io.legado.app.utils
 
 
+import io.legado.app.exception.NoStackTraceException
+import io.legado.app.help.CrashHandler
 import kotlinx.coroutines.suspendCancellableCoroutine
 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)