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

Android WebView迁移AJAX到Fetch API调用自定义URL遇错误求助

解决Android WebView中Fetch API无法加载自定义URL的问题

我明白你遇到的困扰了——原来用XMLHttpRequest能正常被WebView拦截的请求,换成Fetch API后就触发了scheme不支持的错误。这是因为Fetch API在WebView中的安全策略和XHR有差异,而且它对URL的解析逻辑更严格,把你的data//app:customers识别成了file://协议的路径,而Fetch默认禁止加载file scheme的资源。

下面是具体的解决方案:

1. 改用自定义URL Scheme

首先把你的请求URL改成标准的自定义scheme格式,比如app://customers,这样WebView会把它识别为自定义协议,而不是file路径。修改后的Fetch代码:

fetch("app://customers")
  .then(response => response.json()) // 记得解析响应,原代码只是返回data未做处理
  .then(data => {
    console.log("获取到数据:", data);
    // 这里处理你的业务逻辑
  })
  .catch(error => console.error("请求出错:", error));

2. 调整WebView的拦截逻辑

接下来在Android代码中,修改shouldInterceptRequest来拦截这个自定义scheme的请求,同时处理可能的OPTIONS预请求(Fetch会自动发送OPTIONS请求做CORS校验):

override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest?): WebResourceResponse? {
    val requestUrl = request?.url?.toString() ?: return super.shouldInterceptRequest(view, request)

    // 处理OPTIONS预请求,解决CORS问题
    if (request.method.equals("OPTIONS", ignoreCase = true) && requestUrl.startsWith("app://")) {
        val corsHeaders = mapOf(
            "Access-Control-Allow-Origin" to "*",
            "Access-Control-Allow-Methods" to "GET, POST, OPTIONS",
            "Access-Control-Allow-Headers" to "Content-Type"
        )
        return WebResourceResponse(
            "text/plain",
            "UTF-8",
            200,
            "OK",
            corsHeaders,
            ByteArrayInputStream("".toByteArray(Charsets.UTF_8))
        )
    }

    // 拦截自定义scheme的GET请求
    if (requestUrl.startsWith("app://")) {
        val resourcePath = requestUrl.substring("app://".length)
        return when (resourcePath) {
            "customers" -> {
                // 生成模拟数据并转换为输入流
                val fakeCustomers = Customer.fakeData(1)
                val jsonString = Shared.jsonToStr(fakeCustomers) // 假设你有这个JSON转换方法
                val inputStream = ByteArrayInputStream(jsonString.toByteArray(Charsets.UTF_8))
                // 返回正确的响应类型,这里用application/json更合适
                WebResourceResponse("application/json", "UTF-8", inputStream)
            }
            // 可以添加更多资源路径的处理逻辑
            else -> super.shouldInterceptRequest(view, request)
        }
    }

    return super.shouldInterceptRequest(view, request)
}

3. 配置WebView的必要设置

确保你的WebView设置允许自定义scheme的加载,以及相关的权限:

webView.settings.apply {
    allowFileAccess = true
    allowContentAccess = true
    // 如果你的页面是从file://加载的,需要开启这个选项来允许跨域请求
    setAllowUniversalAccessFromFileURLs(true)
}

为什么原来的XHR能工作?

原来的同步XMLHttpRequest请求,WebView的拦截机制能直接捕获并处理,而且XHR对URL的解析没有Fetch那么严格,没有把data//app:customers识别为file scheme。而Fetch API遵循更严格的浏览器安全规范,禁止加载file协议的资源,所以必须改用自定义scheme来绕过这个限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:28:42