Jetpack Compose WebView加载m.bilibili.com样式不完整的问题排查与修复咨询
Jetpack Compose WebView加载m.bilibili.com样式不完整的问题排查与修复咨询
嘿,我来帮你搞定这个问题!我之前也碰过WebView加载特定站点样式异常的情况,尤其是像B站这种对移动端环境比较敏感的站点,咱们一步步来排查和修复。
一、核心问题推测:User-Agent不匹配导致资源加载被拦截
B站的移动端站点会根据请求的User-Agent(UA)返回适配的资源,如果WebView默认的UA和手机系统浏览器的UA差异太大,B站可能会拒绝加载部分样式表,或者返回非移动端的适配资源,这是这类问题最常见的诱因。
二、必要的WebSettings补充配置
你的现有配置只开了基础的JS和DOM存储,但还有几个关键配置没加,这些会直接影响资源加载和页面渲染逻辑:
适配移动端的User-Agent设置
直接复用系统浏览器的UA,或者设置一个和你三星S24系统浏览器完全一致的UA(可以通过系统浏览器访问本地检测页面获取),让B站认为当前是正常的移动端浏览器请求:// 用系统默认UA,和你的三星S24浏览器保持一致 settings.userAgentString = WebSettings.getDefaultUserAgent(context)开启自适应屏幕的关键配置
这两个设置能让WebView正确识别移动端页面的视口规则,避免样式错位或资源加载范围异常:settings.useWideViewPort = true // 支持自适应视口宽度 settings.loadWithOverviewMode = true // 按屏幕宽度自动缩放加载页面补充资源加载相关配置
加上这些配置,覆盖B站可能用到的交互和资源加载规则:settings.javaScriptCanOpenWindowsAutomatically = true // 支持JS打开新窗口,适配B站的部分交互 settings.cacheMode = WebSettings.LOAD_DEFAULT // 遵循默认缓存策略,避免重复请求被拦截 settings.mediaPlaybackRequiresUserGesture = false // 允许自动播放媒体(B站移动端部分内容依赖)
三、WebViewClient的优化与排查手段
你当前的WebViewClient是空实现,我们可以加一些日志排查逻辑,确认是哪些样式表没被请求,以及页面加载的状态:
webViewClient = object : WebViewClient() { // 打印所有CSS请求,排查是否有遗漏 override fun shouldInterceptRequest( view: WebView?, request: WebResourceRequest? ): WebResourceResponse? { request?.url?.let { url -> if (url.path.contains(".css")) { println("检测到CSS请求: ${url.toString()}") } } return super.shouldInterceptRequest(view, request) } // 页面加载完成后检查已加载的样式表数量 override fun onPageFinished(view: WebView?, url: String?) { super.onPageFinished(view, url) view?.evaluateJavascript("document.querySelectorAll('link[rel=stylesheet]').length") { count -> println("已成功加载的样式表数量: $count") } } }
通过这些日志,你能快速确认是B站没返回样式表,还是WebView没触发请求,或者请求被拦截了。
四、代码逻辑的小优化
你代码里的LaunchedEffect加了2秒延迟完全没必要,而且直接用webViewSource!!有潜在空指针风险,咱们把这部分简化:
LaunchedEffect(Unit) { // 去掉无意义的延迟,用安全调用避免空指针 webViewSource?.let { it.loadUrl("https://m.bilibili.com/") } }
五、完整修复后的代码
最后把所有修改整合起来,给你一个可直接用的版本:
@Composable fun WebViewPage() { println("[recomposable] - WebViewPage") var webViewSource: WebView? by remember { mutableStateOf(null) } LaunchedEffect(Unit) { webViewSource?.let { it.loadUrl("https://m.bilibili.com/") } } AndroidView( modifier = Modifier.fillMaxSize(), factory = { context -> WebView(context).apply { // Cookie配置提前初始化 val cookieManager = CookieManager.getInstance() cookieManager.setAcceptThirdPartyCookies(this, true) cookieManager.setAcceptCookie(true) settings.apply { // 保留原有基础配置 javaScriptEnabled = true domStorageEnabled = true mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW loadsImagesAutomatically = true // 新增的关键配置 userAgentString = WebSettings.getDefaultUserAgent(context) useWideViewPort = true loadWithOverviewMode = true javaScriptCanOpenWindowsAutomatically = true cacheMode = WebSettings.LOAD_DEFAULT mediaPlaybackRequiresUserGesture = false } webViewClient = object : WebViewClient() { override fun shouldInterceptRequest( view: WebView?, request: WebResourceRequest? ): WebResourceResponse? { request?.url?.let { url -> if (url.path.contains(".css")) { println("检测到CSS请求: ${url.toString()}") } } return super.shouldInterceptRequest(view, request) } override fun onPageFinished(view: WebView?, url: String?) { super.onPageFinished(view, url) view?.evaluateJavascript("document.querySelectorAll('link[rel=stylesheet]').length") { count -> println("已成功加载的样式表数量: $count") } } } loadUrl("about:blank") }.also { webViewSource = it } }, update = { /* 不需要额外更新逻辑,留空即可 */ } ) }
最后再提几个排查小技巧
- 用Chrome远程调试WebView:在Chrome地址栏输入
chrome://inspect,找到你的App对应的WebView,就能像调试普通网页一样查看控制台错误、网络请求详情,快速定位是样式表403了,还是JS报错导致样式没渲染。 - 完全匹配系统UA:如果还是不行,你可以把WebView的UA改成你三星S24系统浏览器的真实UA,进一步规避B站的特征检测。
试试这些修改,应该就能解决样式不完整的问题啦!如果还有问题,咱们再接着排查~




