package top.yeij.hearth.webview import android.annotation.SuppressLint import android.app.Activity import android.graphics.Color import android.view.ViewGroup import android.webkit.WebView import android.webkit.WebViewClient // WebView 工厂:统一内核配置,桌面层挂到指定父容器,内容层按需创建 // WebView factory: unified kernel config; the desktop layer attaches to a given // parent container, content layers are created on demand class WebViewManager(private val activity: Activity) { // 创建桌面 WebView(底层 H5)挂到 parent,加载内置 index.html // Create the desktop WebView (bottom H5 layer) under parent, load bundled index.html @SuppressLint("SetJavaScriptEnabled") fun attach(bridge: JsBridge, parent: ViewGroup): WebView { val webView = WebView(activity) webView.setBackgroundColor(Color.TRANSPARENT) configure(webView) webView.addJavascriptInterface(bridge, "HearthBridge") webView.webViewClient = WebViewClient() webView.loadUrl("file:///android_asset/h5/index.html") parent.addView(webView, ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)) return webView } // 创建内容 WebView(webAPP 标签页),仅配置不加载、不挂载(由宿主管理) // 透明背景:webAPP 未声明背景色时透出桌面壁纸,而非默认白底 // Create a content WebView (webapp tab), configured but not loaded/attached // (lifecycle is managed by the host); transparent background so a webapp without // a declared background shows the wallpaper instead of a default white @SuppressLint("SetJavaScriptEnabled") fun createContentWebView(ua: String?, scale: Int?): WebView { val webView = WebView(activity) webView.setBackgroundColor(Color.TRANSPARENT) configure(webView) // UA 解析:desktop/pc → PC UA;自定义字符串 → 直接用;null → 默认平板 UA // UA resolution: desktop/pc -> desktop UA; custom string -> used as-is; // null -> default tablet UA webView.settings.userAgentString = when { ua == null -> UA_TABLET ua == "desktop" || ua == "pc" -> UA_DESKTOP else -> ua } // scale 由 WebAppHost 在 onPageFinished 里通过 CSS zoom 实现(reflow 缩放), // 此处不再做 View 级别缩放 // scale is applied by WebAppHost via CSS zoom in onPageFinished (reflow // scaling); no view-level scaling here return webView } // 统一内核配置:JS、宽视口、DOM 存储,禁用缩放 // Common kernel config: JS, wide viewport, DOM storage, zoom disabled @SuppressLint("SetJavaScriptEnabled") private fun configure(webView: WebView) { webView.settings.apply { javaScriptEnabled = true useWideViewPort = true loadWithOverviewMode = true setSupportZoom(false) domStorageEnabled = true // Android 11 + targetSdk 30 默认禁用 file:// 访问,本地离线包需要显式开启 // Android 11 + targetSdk 30 disables file:// by default; local offline // packages need it explicitly enabled allowFileAccess = true allowContentAccess = true } } companion object { // PC 版 UA(desktop/pc) private const val UA_DESKTOP = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " + "(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" // 安卓平板 UA(默认) private const val UA_TABLET = "Mozilla/5.0 (Linux; Android 13; SM-X700 Build/TP1A.220624.014) " + "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" } }