You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android开发:如何在WebView中模拟本地服务器并加载assets站点资源?

WebView加载本地assets网站完整操作步骤

1. 完成WebView基础配置

在加载页面对应的Activity/Fragment中,对WebView做如下必要配置,否则会出现JS失效、资源无法加载的问题:

// 取到WebView实例后配置参数
val webSettings = webView.settings
// 启用JavaScript支持,必开,大部分前端站都依赖JS
webSettings.javaScriptEnabled = true
// 允许WebView访问本地文件
webSettings.allowFileAccess = true
// 允许JS跨域访问文件资源,解决本地绝对路径资源跨域报错问题
webSettings.allowUniversalAccessFromFileURLs = true
// 启用DOM存储,支持localStorage、sessionStorage等前端存储能力
webSettings.domStorageEnabled = true
// 强制所有页面跳转、资源请求都在当前WebView处理,不跳系统浏览器
webView.webViewClient = WebViewClient()

如果你的应用需要加载站外资源,需要在AndroidManifest.xml中添加网络权限:

<uses-permission android:name="android.permission.INTERNET" />

完全本地运行的站点不需要添加该权限。

2. 加载assets目录下的入口文件

Android assets目录下的资源固定通过file:///android_asset/前缀访问,假设你网站的入口是根目录下的index.html,加载代码如下:

webView.loadUrl("file:///android_asset/index.html")

如果你的网站代码全部放在assets下的子目录(比如assets/web/),则加载地址改为file:///android_asset/web/index.html,路径必须和实际目录结构完全匹配

3. 拦截请求模拟服务端路径映射

如果你的网站使用了绝对路径引用资源(比如/css/main.css)、或者代码里写死了原服务端域名的请求,直接加载会出现资源找不到的问题,需要重写WebViewClient的shouldInterceptRequest方法做路径映射:

webView.webViewClient = object : WebViewClient() {
    override fun shouldInterceptRequest(
        view: WebView?,
        request: WebResourceRequest
    ): WebResourceResponse? {
        val requestUrl = request.url.toString()
        // 替换为你原服务端的域名,匹配所有原站请求
        if (requestUrl.startsWith("https://your-original-domain.com/")) {
            // 提取域名后的路径部分,比如https://xxx.com/css/main.css 提取到 css/main.css
            val assetRelativePath = requestUrl.removePrefix("https://your-original-domain.com/")
            return try {
                // 打开assets下对应路径的资源
                val inputStream = assets.open(assetRelativePath)
                // 根据资源后缀匹配MIME类型
                val mimeType = when {
                    assetRelativePath.endsWith(".html") -> "text/html"
                    assetRelativePath.endsWith(".css") -> "text/css"
                    assetRelativePath.endsWith(".js") -> "application/javascript"
                    assetRelativePath.endsWith(".png") -> "image/png"
                    assetRelativePath.endsWith(".jpg", ignoreCase = true) || assetRelativePath.endsWith(".jpeg", ignoreCase = true) -> "image/jpeg"
                    assetRelativePath.endsWith(".svg") -> "image/svg+xml"
                    else -> "application/octet-stream"
                }
                WebResourceResponse(mimeType, "UTF-8", inputStream)
            } catch (e: Exception) {
                // 找不到对应资源走系统默认逻辑
                super.shouldInterceptRequest(view, request)
            }
        }
        // 非原站请求走默认逻辑
        return super.shouldInterceptRequest(view, request)
    }
}

如果有后端接口请求,也可以在该方法中拦截接口路径,直接返回本地预置的JSON数据,完全模拟服务端接口响应

4. 特殊场景兼容

  • 单页应用(Vue/React等)路由:如果用的是history模式路由,需要在拦截方法中将所有路由请求都映射到入口index.html文件
  • 服务端动态内容:如果原站有服务端渲染的动态内容,需要提前做静态化处理,或者在拦截请求时本地生成对应内容返回
  • 跨域请求:如果原站有跨域调用第三方接口的逻辑,已经开了allowUniversalAccessFromFileURLs的前提下不需要额外处理,如果还有问题可以在拦截方法中代理跨域请求

内容的提问来源于stack exchange,提问作者toto_tata

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 23:24:06