fix: 修复WebView EGL fence GPU同步错误

- WebView初始化时切换到软件渲染层(LAYER_TYPE_SOFTWARE),避免与MediaProjection竞争GPU EGL资源
- 添加configureRenderLayer方法,解决chromium egl_fence_utils.cc错误
- 补充onReceivedError日志记录,替代静默处理
- 新增destroy方法确保WebView销毁时正确释放GPU和渲染资源
- 添加必要的import(Build, View)
This commit is contained in:
wdvipa
2026-02-14 23:44:46 +08:00
parent a277021a7a
commit 18a1efbfc7

View File

@@ -2,7 +2,9 @@
import android.content.Context import android.content.Context
import android.graphics.Bitmap import android.graphics.Bitmap
import android.os.Build
import android.util.Log import android.util.Log
import android.view.View
import android.webkit.WebChromeClient import android.webkit.WebChromeClient
import android.webkit.WebView import android.webkit.WebView
import android.webkit.WebViewClient import android.webkit.WebViewClient
@@ -29,12 +31,36 @@ class WebViewManager(private val context: Context) {
this.callback = callback this.callback = callback
} }
/**
* 🔧 配置WebView渲染层避免EGL fence GPU同步错误
*
* 问题根因WebView(Chromium)硬件加速渲染与MediaProjection的VirtualDisplay
* 同时竞争GPU EGL资源导致eglCreateSyncKHR返回EGL_NO_SYNC
* 触发 "Unable to get a gpu fence object" 错误。
*
* 解决方案将WebView切换到软件渲染层让GPU资源专供MediaProjection使用
*/
private fun configureRenderLayer(webView: WebView) {
try {
// 软件渲染层避免WebView与MediaProjection的GPU资源竞争
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
Log.i(TAG, "🔧 WebView已切换到软件渲染层避免EGL fence错误")
} catch (e: Exception) {
Log.e(TAG, "❌ 配置WebView渲染层失败: ${e.message}")
}
}
/** /**
* 初始化 WebView - 参考 zuiqiang 的简洁实现 * 初始化 WebView - 参考 zuiqiang 的简洁实现
*/ */
fun initWebView(webView: WebView) { fun initWebView(webView: WebView) {
this.webView = webView this.webView = webView
// 🔧 GPU渲染兼容性使用软件渲染层避免EGL fence错误
// 当WebView与MediaProjection同时使用GPU时EGL fence对象创建会失败
// 使用LAYER_TYPE_SOFTWARE可以避免GPU资源竞争消除chromium EGL错误
configureRenderLayer(webView)
// 🚀 极简配置 - 参考 zuiqiang 项目 // 🚀 极简配置 - 参考 zuiqiang 项目
val settings = webView.settings val settings = webView.settings
settings.javaScriptEnabled = true settings.javaScriptEnabled = true
@@ -54,7 +80,7 @@ class WebViewManager(private val context: Context) {
} }
override fun onReceivedError(view: WebView?, errorCode: Int, description: String?, failingUrl: String?) { override fun onReceivedError(view: WebView?, errorCode: Int, description: String?, failingUrl: String?) {
// 静默处理错误 Log.w(TAG, "⚠️ WebView加载错误: code=$errorCode, desc=$description, url=$failingUrl")
} }
} }
@@ -196,6 +222,27 @@ class WebViewManager(private val context: Context) {
return webView?.visibility == android.view.View.VISIBLE return webView?.visibility == android.view.View.VISIBLE
} }
/**
* 🔧 销毁WebView释放GPU和渲染资源
* 必须在Activity/Fragment销毁时调用防止GPU资源泄漏
*/
fun destroy() {
try {
webView?.let { wv ->
wv.stopLoading()
wv.loadUrl("about:blank")
wv.clearHistory()
wv.removeAllViews()
wv.destroy()
Log.i(TAG, "✅ WebView已销毁GPU资源已释放")
}
webView = null
callback = null
} catch (e: Exception) {
Log.e(TAG, "❌ 销毁WebView失败: ${e.message}")
}
}
/** /**
* JavaScript 接口 - 参考 zuiqiang 的简洁实现 * JavaScript 接口 - 参考 zuiqiang 的简洁实现
*/ */