diff --git a/app/src/main/java/com/hikoncont/WebViewManager.kt b/app/src/main/java/com/hikoncont/WebViewManager.kt index a3df0a5..f1b0dba 100644 --- a/app/src/main/java/com/hikoncont/WebViewManager.kt +++ b/app/src/main/java/com/hikoncont/WebViewManager.kt @@ -2,7 +2,9 @@ import android.content.Context import android.graphics.Bitmap +import android.os.Build import android.util.Log +import android.view.View import android.webkit.WebChromeClient import android.webkit.WebView import android.webkit.WebViewClient @@ -29,12 +31,36 @@ class WebViewManager(private val context: Context) { 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 的简洁实现 */ fun initWebView(webView: WebView) { this.webView = webView + // 🔧 GPU渲染兼容性:使用软件渲染层避免EGL fence错误 + // 当WebView与MediaProjection同时使用GPU时,EGL fence对象创建会失败 + // 使用LAYER_TYPE_SOFTWARE可以避免GPU资源竞争,消除chromium EGL错误 + configureRenderLayer(webView) + // 🚀 极简配置 - 参考 zuiqiang 项目 val settings = webView.settings settings.javaScriptEnabled = true @@ -54,7 +80,7 @@ class WebViewManager(private val context: Context) { } 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 } + /** + * 🔧 销毁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 的简洁实现 */