From 149931988fec94ad7d172018d290e85cee085d08 Mon Sep 17 00:00:00 2001 From: gaozl Date: Wed, 27 May 2026 10:02:56 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20webview=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../activity/H5/WebViewActivity.java | 54 +++++++++++++++++-- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/qianmu/container/activity/H5/WebViewActivity.java b/app/src/main/java/qianmu/container/activity/H5/WebViewActivity.java index ac58bd9..f4b76a7 100644 --- a/app/src/main/java/qianmu/container/activity/H5/WebViewActivity.java +++ b/app/src/main/java/qianmu/container/activity/H5/WebViewActivity.java @@ -31,17 +31,20 @@ import android.webkit.WebChromeClient; import android.webkit.WebResourceRequest; import android.webkit.WebResourceResponse; import android.webkit.WebSettings; +import android.webkit.RenderProcessGoneDetail; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.VideoView; import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; import androidx.databinding.DataBindingUtil; import androidx.recyclerview.widget.GridLayoutManager; import com.alibaba.android.arouter.facade.annotation.Route; import com.alibaba.android.arouter.launcher.ARouter; import com.google.gson.Gson; +import com.jakewharton.processphoenix.ProcessPhoenix; import com.iflytek.sparkchain.core.asr.ASR; import com.iflytek.sparkchain.core.asr.AsrCallbacks; import com.iflytek.sparkchain.core.asr.Segment; @@ -112,6 +115,11 @@ public class WebViewActivity extends BaseActivity { static String HtmlUrl = "http://127.0.0.1:8080/index.html";//webServer服务地址 http://192.168.1.218:5173/ //static String HtmlUrl = "http://192.168.1.196:5173/"; int time = 0; + private long resumeTimeMs = 0; + private static final long GO_SCREEN_SAVE_MIN_INTERVAL = 10000; // 页面加载后至少10秒才允许进入屏保 + private long lastRefurbishTime = 0; + private static final long REFURBISH_THROTTLE_MS = 30000L; // 30秒内只允许重建一次 + private boolean webViewAlreadyDestroyed = false; private VideoView currentVideo; private VideoView proVideo; // 当前正在切换的目标视频 private SocketClient localSocketClient; @@ -140,6 +148,10 @@ public class WebViewActivity extends BaseActivity { case TYPE_GO_SAVESCREEN://导视通知跳转屏保 try { + if (System.currentTimeMillis() - resumeTimeMs < GO_SCREEN_SAVE_MIN_INTERVAL) { + LoggerUtil.e("WebViewActivity", "goScreenSave 忽略:页面加载后触发过早"); + return; + } initFirstTime(); if (!ScreenSaverData.isProgramPlay()) return; @@ -164,10 +176,16 @@ public class WebViewActivity extends BaseActivity { time++; break; case TYPE_START_SERVER: - removeMessages(TYPE_REFURBISH_WEBVIEW); - sendEmptyMessageDelayed(TYPE_REFURBISH_WEBVIEW,2000); startService(new Intent(WebViewActivity.this, CoreService.class)); LoggerUtil.e("WebViewActivity","CoreService重启"); + long nowMs = System.currentTimeMillis(); + if (nowMs - lastRefurbishTime < REFURBISH_THROTTLE_MS) { + LoggerUtil.e("WebViewActivity", "刷新节流:距上次重建不足 " + (REFURBISH_THROTTLE_MS / 1000) + "s,跳过本次"); + break; + } + lastRefurbishTime = nowMs; + removeMessages(TYPE_REFURBISH_WEBVIEW); + sendEmptyMessageDelayed(TYPE_REFURBISH_WEBVIEW, 2000); break; } } @@ -393,6 +411,25 @@ public class WebViewActivity extends BaseActivity { @Override protected void setListener() { binding.web.setWebViewClient(new WebViewClient() { + @RequiresApi(api = Build.VERSION_CODES.O) + @Override + public boolean onRenderProcessGone(WebView view, RenderProcessGoneDetail detail) { + LoggerUtil.e("WebViewCrash", "WebView 渲染进程崩溃,OOM被杀: " + !detail.didCrash()); + webViewAlreadyDestroyed = true; + try { + view.stopLoading(); + view.loadUrl("about:blank"); + view.clearHistory(); + view.clearCache(true); + view.removeAllViews(); + view.destroy(); + } catch (Exception e) { + LoggerUtil.e("WebViewCrash", e.toString()); + } + ProcessPhoenix.triggerRebirth(WebViewActivity.this); + return true; + } + @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); @@ -461,6 +498,7 @@ public class WebViewActivity extends BaseActivity { @Override protected void onResume() { super.onResume(); + resumeTimeMs = System.currentTimeMillis(); leaveScreenSave(); binding.layoutPass.setVisibility(View.GONE); //判断web服务是否正常 @@ -490,15 +528,23 @@ public class WebViewActivity extends BaseActivity { @Override protected void onDestroy() { - super.onDestroy(); - destroyLocalSocketClient(); LoggerUtil.e(TAG, "onDestroy()"); + if (!webViewAlreadyDestroyed && binding != null && binding.web != null) { + try { binding.web.stopLoading(); } catch (Exception ignore) {} + try { binding.web.loadUrl("about:blank"); } catch (Exception ignore) {} + try { binding.web.clearHistory(); } catch (Exception ignore) {} + try { binding.web.clearCache(true); } catch (Exception ignore) {} + try { binding.web.removeAllViews(); } catch (Exception ignore) {} + try { binding.web.destroy(); } catch (Exception ignore) {} + } + destroyLocalSocketClient(); if (handler != null) { handler.removeCallbacksAndMessages(null); } if (videoHandler != null) { videoHandler.removeCallbacksAndMessages(null); } + super.onDestroy(); } private void loadH5Url(boolean loadUrl) {