This commit is contained in:
Horis 2024-01-25 22:08:24 +08:00
parent 5324dfcec3
commit d1064c5b4c
17 changed files with 176 additions and 4 deletions

View File

@ -144,6 +144,7 @@ object PreferKey {
const val volumeKeyPage = "volumeKeyPage"
const val volumeKeyPageOnPlay = "volumeKeyPageOnPlay"
const val mouseWheelPage = "mouseWheelPage"
const val recordHeapDump = "recordHeapDump"
const val cPrimary = "colorPrimary"
const val cAccent = "colorAccent"

View File

@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.content.Context
import android.net.Uri
import android.os.Build
import android.os.Debug
import android.os.Looper
import android.webkit.WebSettings
import io.legado.app.constant.AppConst
@ -12,13 +13,24 @@ import io.legado.app.exception.NoStackTraceException
import io.legado.app.help.config.AppConfig
import io.legado.app.help.config.LocalConfig
import io.legado.app.model.ReadAloud
import io.legado.app.utils.*
import io.legado.app.utils.FileDoc
import io.legado.app.utils.FileUtils
import io.legado.app.utils.createFileIfNotExist
import io.legado.app.utils.createFolderReplace
import io.legado.app.utils.externalCache
import io.legado.app.utils.getFile
import io.legado.app.utils.longToastOnUiLegacy
import io.legado.app.utils.stackTraceStr
import io.legado.app.utils.writeText
import splitties.init.appCtx
import java.io.PrintWriter
import java.io.StringWriter
import java.text.SimpleDateFormat
import java.util.*
import java.util.Date
import java.util.concurrent.TimeUnit
import kotlin.collections.component1
import kotlin.collections.component2
import kotlin.collections.set
/**
* 异常管理类
@ -69,6 +81,9 @@ class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler {
LocalConfig.appCrash = true
//保存日志文件
saveCrashInfo2File(ex)
if (ex is OutOfMemoryError && AppConfig.recordHeapDump) {
doHeapDump()
}
context.longToastOnUiLegacy(ex.stackTraceStr)
Thread.sleep(3000)
}
@ -148,6 +163,19 @@ class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler {
}
}
/**
* 进行堆转储
*/
fun doHeapDump() {
val heapDir = appCtx
.externalCache
.getFile("heapDump")
heapDir.createFolderReplace()
val heapFile = heapDir.getFile("heap-dump-${System.currentTimeMillis()}.hprof")
val heapDumpName = heapFile.absolutePath
Debug.dumpHprofData(heapDumpName)
}
}
}

View File

@ -449,6 +449,8 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
val recordLog get() = appCtx.getPrefBoolean(PreferKey.recordLog)
val recordHeapDump get() = appCtx.getPrefBoolean(PreferKey.recordHeapDump, false)
val loadCoverOnlyWifi get() = appCtx.getPrefBoolean(PreferKey.loadCoverOnlyWifi, false)
val showAddToShelfAlert get() = appCtx.getPrefBoolean(PreferKey.showAddToShelfAlert, true)

View File

@ -12,6 +12,7 @@ import io.legado.app.R
import io.legado.app.constant.AppConst.appInfo
import io.legado.app.constant.AppLog
import io.legado.app.help.AppUpdate
import io.legado.app.help.CrashHandler
import io.legado.app.help.config.AppConfig
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.ui.widget.dialog.TextDialog
@ -61,6 +62,7 @@ class AboutFragment : PreferenceFragmentCompat() {
"gzGzh" -> requireContext().sendToClip(getString(R.string.legado_gzh))
"crashLog" -> showDialogFragment<CrashLogsDialog>()
"saveLog" -> saveLog()
"saveHeapDump" -> saveHeapDump()
}
return super.onPreferenceTreeClick(preference)
}
@ -137,10 +139,50 @@ class AboutFragment : PreferenceFragmentCompat() {
}
}
}
val heapFile = FileDoc.fromFile(File(appCtx.externalCacheDir, "heapDump")).list()
?.firstOrNull()
if (heapFile != null) {
doc.find("heapDump")?.delete()
val heapDumpDoc = doc.createFolderIfNotExist("heapDump")
heapFile.openInputStream().getOrNull()?.use { input ->
heapDumpDoc.createFileIfNotExist(heapFile.name).openOutputStream().getOrNull()
?.use {
input.copyTo(it)
}
}
}
toastOnUi("已保存至备份目录")
}.onError {
AppLog.put("保存日志出错\n${it.localizedMessage}", it, true)
}
}
private fun saveHeapDump() {
Coroutine.async {
val backupPath = AppConfig.backupPath ?: let {
toastOnUi("未设置备份目录")
return@async
}
toastOnUi("开始保存堆转储")
CrashHandler.doHeapDump()
val heapFile = FileDoc.fromFile(File(appCtx.externalCacheDir, "heapDump")).list()
?.firstOrNull() ?: let {
toastOnUi("未找到堆转储文件")
return@async
}
val doc = FileDoc.fromUri(Uri.parse(backupPath), true)
doc.find("heapDump")?.delete()
val heapDumpDoc = doc.createFolderIfNotExist("heapDump")
heapFile.openInputStream().getOrNull()?.use { input ->
heapDumpDoc.createFileIfNotExist(heapFile.name).openOutputStream().getOrNull()
?.use {
input.copyTo(it)
}
}
toastOnUi("已保存至备份目录")
}.onError {
AppLog.put("保存堆转储失败\n${it.localizedMessage}", it)
}
}
}

View File

@ -2,12 +2,19 @@ package io.legado.app.ui.login
import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.net.Uri
import android.net.http.SslError
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.webkit.*
import android.webkit.CookieManager
import android.webkit.SslErrorHandler
import android.webkit.WebChromeClient
import android.webkit.WebResourceRequest
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.fragment.app.activityViewModels
import io.legado.app.R
import io.legado.app.base.BaseFragment
@ -16,8 +23,10 @@ import io.legado.app.data.entities.BaseSource
import io.legado.app.databinding.FragmentWebViewLoginBinding
import io.legado.app.help.http.CookieStore
import io.legado.app.lib.theme.accentColor
import io.legado.app.utils.gone
import io.legado.app.utils.NetworkUtils
import io.legado.app.utils.gone
import io.legado.app.utils.longSnackbar
import io.legado.app.utils.openUrl
import io.legado.app.utils.snackbar
import io.legado.app.utils.viewbindingdelegate.viewBinding
@ -89,6 +98,33 @@ class WebViewLoginFragment : BaseFragment(R.layout.fragment_web_view_login) {
super.onPageFinished(view, url)
}
override fun shouldOverrideUrlLoading(
view: WebView,
request: WebResourceRequest
): Boolean {
return shouldOverrideUrlLoading(request.url)
}
@Suppress("DEPRECATION", "OVERRIDE_DEPRECATION", "KotlinRedundantDiagnosticSuppress")
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
return shouldOverrideUrlLoading(Uri.parse(url))
}
private fun shouldOverrideUrlLoading(url: Uri): Boolean {
when (url.scheme) {
"http", "https" -> {
return false
}
else -> {
binding.root.longSnackbar(R.string.jump_to_another_app, R.string.confirm) {
context?.openUrl(url)
}
return true
}
}
}
@SuppressLint("WebViewClientOnReceivedSslError")
override fun onReceivedSslError(
view: WebView?,

View File

@ -1141,4 +1141,7 @@
<string name="clear_webview_data_success">清除成功3秒后自动重启应用</string>
<string name="key_page_on_long_press">按键长按翻页</string>
<string name="save_log">保存日志</string>
<string name="save_heap_dump">保存堆转储</string>
<string name="record_heap_dump_s">当应用发生OOM崩溃时保存堆转储</string>
<string name="record_heap_dump_t">记录堆转储</string>
</resources>

View File

@ -1144,4 +1144,7 @@
<string name="clear_webview_data_success">清除成功3秒后自动重启应用</string>
<string name="key_page_on_long_press">按键长按翻页</string>
<string name="save_log">保存日志</string>
<string name="save_heap_dump">保存堆转储</string>
<string name="record_heap_dump_s">当应用发生OOM崩溃时保存堆转储</string>
<string name="record_heap_dump_t">记录堆转储</string>
</resources>

View File

@ -1144,4 +1144,7 @@
<string name="clear_webview_data_success">清除成功3秒后自动重启应用</string>
<string name="key_page_on_long_press">按键长按翻页</string>
<string name="save_log">保存日志</string>
<string name="save_heap_dump">保存堆转储</string>
<string name="record_heap_dump_s">当应用发生OOM崩溃时保存堆转储</string>
<string name="record_heap_dump_t">记录堆转储</string>
</resources>

View File

@ -1140,4 +1140,7 @@ Còn </string>
<string name="clear_webview_data_success">清除成功3秒后自动重启应用</string>
<string name="key_page_on_long_press">按键长按翻页</string>
<string name="save_log">保存日志</string>
<string name="save_heap_dump">保存堆转储</string>
<string name="record_heap_dump_s">当应用发生OOM崩溃时保存堆转储</string>
<string name="record_heap_dump_t">记录堆转储</string>
</resources>

View File

@ -1141,4 +1141,7 @@
<string name="clear_webview_data_success">清除成功3秒后自动重启应用</string>
<string name="key_page_on_long_press">按键长按翻页</string>
<string name="save_log">保存日志</string>
<string name="save_heap_dump">保存堆转储</string>
<string name="record_heap_dump_s">当应用发生OOM崩溃时保存堆转储</string>
<string name="record_heap_dump_t">记录堆转储</string>
</resources>

View File

@ -1143,4 +1143,7 @@
<string name="clear_webview_data_success">清除成功3秒后自动重启应用</string>
<string name="key_page_on_long_press">按键长按翻页</string>
<string name="save_log">保存日志</string>
<string name="save_heap_dump">保存堆转储</string>
<string name="record_heap_dump_s">当应用发生OOM崩溃时保存堆转储</string>
<string name="record_heap_dump_t">记录堆转储</string>
</resources>

View File

@ -1143,4 +1143,7 @@
<string name="clear_webview_data_success">清除成功3秒后自动重启应用</string>
<string name="key_page_on_long_press">按键长按翻页</string>
<string name="save_log">保存日志</string>
<string name="save_heap_dump">保存堆转储</string>
<string name="record_heap_dump_s">当应用发生OOM崩溃时保存堆转储</string>
<string name="record_heap_dump_t">记录堆转储</string>
</resources>

View File

@ -1144,4 +1144,7 @@
<string name="clear_webview_data_success">Cleared successfully, automatically restarts the application after 3 seconds</string>
<string name="key_page_on_long_press">Press and hold the key to turn the page</string>
<string name="save_log">保存日志</string>
<string name="save_heap_dump">保存堆转储</string>
<string name="record_heap_dump_s">当应用发生OOM崩溃时保存堆转储</string>
<string name="record_heap_dump_t">记录堆转储</string>
</resources>

View File

@ -39,6 +39,11 @@
android:title="@string/save_log"
app:iconSpaceReserved="false" />
<io.legado.app.lib.prefs.Preference
android:key="saveHeapDump"
android:title="@string/save_heap_dump"
app:iconSpaceReserved="false" />
<io.legado.app.lib.prefs.Preference
android:key="privacyPolicy"
android:title="@string/privacy_policy"

View File

@ -188,6 +188,13 @@
android:title="@string/record_log"
app:iconSpaceReserved="false" />
<io.legado.app.lib.prefs.SwitchPreference
android:defaultValue="false"
android:key="recordHeapDump"
android:summary="@string/record_heap_dump_s"
android:title="@string/record_heap_dump_t"
app:iconSpaceReserved="false" />
</io.legado.app.lib.prefs.PreferenceCategory>

View File

@ -3,6 +3,8 @@
*/
package com.script
import org.mozilla.javascript.Scriptable
abstract class CompiledScript {
abstract fun getEngine(): ScriptEngine
@ -10,6 +12,9 @@ abstract class CompiledScript {
@Throws(ScriptException::class)
abstract fun eval(context: ScriptContext): Any?
@Throws(ScriptException::class)
abstract fun eval(scope: Scriptable): Any?
@Throws(ScriptException::class)
fun eval(bindings: Bindings?): Any? {
var ctxt = getEngine().context

View File

@ -69,4 +69,26 @@ internal class RhinoCompiledScript(
return result
}
override fun eval(scope: Scriptable): Any? {
val cx = Context.enter()
val result: Any?
try {
val ret = script.exec(cx, scope)
result = engine.unwrapReturnValue(ret)
} catch (re: RhinoException) {
val line = if (re.lineNumber() == 0) -1 else re.lineNumber()
val msg: String = if (re is JavaScriptException) {
re.value.toString()
} else {
re.toString()
}
val se = ScriptException(msg, re.sourceName(), line)
se.initCause(re)
throw se
} finally {
Context.exit()
}
return result
}
}