Android webview拦截H5的接口请求并返回处理好的数据

Android webview拦截H5的接口请求并返回处理好的数据

Android 可以通过 WebViewshouldInterceptRequest 方法拦截到 H5 中的网络请求。这是一个 WebViewClient 中的回调方法,允许开发者在 WebView 发起网络请求时对其进行处理和修改。

具体使用方法如下:

  1. 你需要创建一个自定义的 WebViewClient,并重写 shouldInterceptRequest 方法。

  2. 在该方法中,你可以拦截 WebView 发起的网络请求,并返回一个自定义的响应,或让请求继续。

  3. 该方法在 API 21 (Android 5.0) 及更高版本中引入了两个重载方法:

    • shouldInterceptRequest(WebView view, String url) (API 11)
    • shouldInterceptRequest(WebView view, WebResourceRequest request) (API 21)

以下是代码示例:

// Kotlin 代码示例
webView.webViewClient = object : WebViewClient() {// 对于 API 21 及更高版本override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {val url = request.url.toString()// 这里你可以判断 URL,并根据需要拦截或修改请求if (url.contains("your_target_url")) {// 可以在这里做一些处理,例如替换请求或返回本地数据val inputStream = ... // 自定义输入流return WebResourceResponse("text/html", "UTF-8", inputStream)}// 不拦截,继续请求return super.shouldInterceptRequest(view, request)}// 对于 API 11 到 API 20 的设备override fun shouldInterceptRequest(view: WebView, url: String): WebResourceResponse? {// 这里处理逻辑类似于上面的代码if (url.contains("your_target_url")) {// 自定义处理逻辑val inputStream = ... return WebResourceResponse("text/html", "UTF-8", inputStream)}return super.shouldInterceptRequest(view, url)}
}

shouldInterceptRequest 方法中,你可以返回一个 WebResourceResponse 对象,来改变或替换原始的网络请求,也可以通过默认实现让请求继续执行。

获取网络接口请求的数据(如 API 请求的响应),然后将其返回给 H5,

有以下几种方式可以考虑:

1. 拦截请求并手动发起请求

你可以通过 shouldInterceptRequest 方法拦截 WebView 的 API 请求,自己在 Java 或 Kotlin 中使用 HttpURLConnectionOkHttp 发起网络请求,处理完响应后,再将响应数据传递给 H5。

示例代码:

webView.webViewClient = object : WebViewClient() {override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {val url = request.url.toString()// 判断是否是需要拦截的接口请求if (url.contains("your_api_endpoint")) {// 通过 OkHttp 或 HttpURLConnection 发起请求val response = fetchApiData(url)// 将获取的响应内容传递给 H5view.post {view.evaluateJavascript("javascript:handleApiResponse('${response}')", null)}// 返回一个空响应或自定义内容return WebResourceResponse("application/json", "UTF-8", null)}return super.shouldInterceptRequest(view, request)}// 使用 OkHttp 发起网络请求(可以根据你的需求选择合适的网络库)private fun fetchApiData(url: String): String {// 简单 OkHttp 请求示例val client = OkHttpClient()val request = Request.Builder().url(url).build()client.newCall(request).execute().use { response ->return response.body?.string() ?: ""}}
}

在这个例子中,shouldInterceptRequest 会拦截指定的网络请求,然后用 OkHttp 发起请求,并将获取的响应数据通过 evaluateJavascript 方法传回到 WebView 中的 H5 页面。

2. 通过 WebView 和 H5 的 JavaScript 通信

另一种方式是通过 WebView 的 addJavascriptInterface 方法,将 Android 代码和 H5 进行通信。当 Android 发起请求后,可以通过接口将数据传递给 H5。

  1. 在 H5 中定义一个 JavaScript 函数,用于接收数据:

function handleApiResponse(response) {console.log("API Response: ", response);// 这里可以对响应进行处理,渲染到页面等
}

       2. 在 Android 端:

webView.addJavascriptInterface(object {@JavascriptInterfacefun sendDataToH5(data: String) {// 发送数据到 H5webView.evaluateJavascript("javascript:handleApiResponse('$data')", null)}
}, "AndroidInterface")webView.webViewClient = object : WebViewClient() {override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {val url = request.url.toString()if (url.contains("your_api_endpoint")) {val response = fetchApiData(url)// 通过 JavaScript 接口传递数据到 H5view.post {view.evaluateJavascript("javascript:AndroidInterface.sendDataToH5('${response}')", null)}return WebResourceResponse("application/json", "UTF-8", null)}return super.shouldInterceptRequest(view, request)}
}

这种需要考虑到H5 发过来的网络接口请求类型吗?post 还是 get

是的,在使用 shouldInterceptRequest 拦截 H5 发过来的网络请求时,需要考虑请求的类型(GET 或 POST)。这是因为 GET 和 POST 请求的处理方式不同,尤其是 POST 请求,它带有请求体(body)数据,而 GET 请求通常只包含 URL 参数。

shouldInterceptRequest 可以帮助你拦截请求,但对于 POST 请求的处理,需要特别注意提取和使用请求体。

如何区分 GET 和 POST 请求?

在 API 21 及更高版本中,shouldInterceptRequest 方法中的 WebResourceRequest 对象包含了更多信息,可以通过它的 getMethod() 方法来区分请求类型。

override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest
): WebResourceResponse? {val url = request.url.toString()val method = request.method  // 获取请求方法,如 GET 或 POST// 根据请求类型处理if (method == "POST") {// 获取 POST 请求的 body(在 Android 的 WebView 中,直接获取 POST body 是不支持的,除非使用特定工具)// 自定义逻辑处理 POST 请求} else if (method == "GET") {// 处理 GET 请求}return super.shouldInterceptRequest(view, request)
}

处理 POST 请求

Android 的 shouldInterceptRequest 本身不直接提供获取 POST 请求体的功能。不过你可以使用其他方式来处理,例如通过在 JS 中提前将请求体通过某种方式传递给 Android。

方法 1:使用 evaluateJavascript 传递 POST 请求数据

你可以让 H5 页面在发出 POST 请求前,通过 JavaScript 提前将 POST 请求的数据发送到 WebView。然后 Android 端可以拦截并处理这些数据。

  1. 在 H5 中拦截和传递 POST 请求数据:

    function interceptAndSendPostData(url, data) {// 调用 Android 接口,将数据传递给 WebViewAndroidInterface.sendPostData(url, JSON.stringify(data));// 继续发起 POST 请求fetch(url, {method: "POST",body: JSON.stringify(data),headers: {"Content-Type": "application/json"}}).then(response => response.json()).then(data => console.log(data));
    }
    
  2. 在 Android 中接收 POST 数据:

    webView.addJavascriptInterface(object {@JavascriptInterfacefun sendPostData(url: String, data: String) {// 这里可以处理传递过来的 POST 请求数据Log.d("WebView", "POST 请求 URL: $url, 数据: $data")}
    }, "AndroidInterface")
    
方法 2:通过自定义网络层发送 POST 请求

另一种方式是在 shouldInterceptRequest 中拦截 POST 请求后,手动发起 HTTP 请求,处理请求体和响应数据。虽然 shouldInterceptRequest 本身不直接提供请求体,但你可以在 H5 页面中通过 JavaScript 提前将 POST 请求体传递给 Android,或者通过其他网络拦截方式处理(例如使用 OkHttp 的拦截器)。

override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest
): WebResourceResponse? {val url = request.url.toString()val method = request.method  // 获取请求方法,如 GET 或 POSTif (method == "POST") {// 自定义发起 HTTP 请求,处理 POST 请求体和响应val response = performCustomHttpPost(url, request)return WebResourceResponse("application/json", "UTF-8", response)}return super.shouldInterceptRequest(view, request)
}fun performCustomHttpPost(url: String, request: WebResourceRequest): InputStream {// 使用 OkHttp 或 HttpURLConnection 发送自定义 POST 请求val client = OkHttpClient()val requestBody = ... // 构建请求体val request = Request.Builder().url(url).post(requestBody).build()val response = client.newCall(request).execute()return response.body?.byteStream() ?: ByteArrayInputStream(ByteArray(0))
}

小结

  • GET 请求:你可以直接通过 URL 和请求头信息来拦截和处理。
  • POST 请求:需要特别处理请求体数据。你可以通过 JavaScript 提前将 POST 请求数据传递给 WebView,或通过手动发起 HTTP 请求处理 POST 请求及其响应。

shouldInterceptRequest 能判断出来网络请求的类型吗?比如script xhr 等

shouldInterceptRequest 本身并不能直接判断网络请求的具体类型(如 scriptxhr 等),因为它没有提供一个字段明确表明请求是某种类型的资源(如 JavaScript 文件、XHR 请求等)。不过,你可以通过请求的 URL请求头信息 来推断请求的类型。

在 API 21 及以上的 Android 版本中,WebResourceRequest 对象提供了丰富的信息,包括请求的 URL、请求方法(GET、POST 等)、请求头等,可以根据这些信息推断请求类型。

如何通过 URL 和请求头判断请求类型?

  1. 通过 URL 后缀

    • 如果请求的 URL 以 .js 结尾,通常可以认为这是一个 script 请求。
    • 如果 URL 中包含 /api/ 或类似的标识符,可能是 xhr 请求。
    • CSS 通常以 .css 结尾,图片文件以 .jpg.png.gif 结尾等。
  2. 通过请求头: 你可以通过请求的头部来推断请求的类型,例如 Accept 头部通常指示客户端期望接收到的数据类型。

    • Accept: application/json 常用于 xhr 请求。
    • Accept: text/css 表示请求 CSS 文件。
    • Accept: application/javascriptAccept: text/javascript 用于 JavaScript 文件请求。

代码示例:如何通过 URL 和请求头推断请求类型

override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest
): WebResourceResponse? {val url = request.url.toString()val headers = request.requestHeadersval acceptHeader = headers["Accept"]  // 获取 Accept 头// 判断是否为脚本请求 (script)if (url.endsWith(".js") || acceptHeader?.contains("application/javascript") == true) {Log.d("WebView", "拦截到脚本请求: $url")// 在此可以拦截或修改脚本请求}// 判断是否为 XHR 请求 (通过 URL 或 Accept 头判断)if (url.contains("/api/") || acceptHeader?.contains("application/json") == true) {Log.d("WebView", "拦截到 XHR 请求: $url")// 在此可以拦截或修改 XHR 请求}// 判断是否为 CSS 请求if (url.endsWith(".css") || acceptHeader?.contains("text/css") == true) {Log.d("WebView", "拦截到 CSS 请求: $url")// 在此可以拦截或修改 CSS 请求}// 其他资源类型的请求Log.d("WebView", "其他类型的请求: $url")return super.shouldInterceptRequest(view, request)
}

常见资源类型的判断方式

  • JavaScript 文件请求 (script)
    • 通过 URL 判断:url.endsWith(".js")
    • 通过 Accept 头判断:application/javascripttext/javascript
  • XHR 请求
    • 通过 URL 规则判断:如果 URL 中包含 /api//ajax/ 或其他常见的 API 路径。
    • 通过 Accept 头判断:application/json
  • CSS 文件请求
    • 通过 URL 判断:url.endsWith(".css")
    • 通过 Accept 头判断:text/css
  • 图片文件请求
    • 通过 URL 判断:url.endsWith(".jpg").png.gif
    • 通过 Accept 头判断:image/*
  • HTML 页面请求
    • 通过 Accept 头判断:text/html

小结

虽然 shouldInterceptRequest 没有直接提供资源类型的字段,但你可以通过 URL 的格式和请求头(特别是 Accept 头)来推断请求的类型,从而拦截特定的资源请求。

script xhr font png preflight 分别是什么,应该怎么判断呢?都可以通过 val acceptHeader = headers["Accept"] 来进行判断吗?

Accept 头在 HTTP 请求中指示客户端希望接收的响应数据类型,它确实能在一些情况下帮助我们判断请求的资源类型。但并不是所有类型的请求都会明确使用 Accept 头。因此,我们需要结合 URL请求头 的其他信息(如 Content-TypeAccess-Control-Request-Method 等)来进行判断。

1. Script(JavaScript 请求)

JavaScript 请求是用来加载 .js 文件的资源请求。

判断依据:

  • URL 后缀:通常 .js 文件后缀。
  • Acceptapplication/javascripttext/javascript
if (url.endsWith(".js") || acceptHeader?.contains("application/javascript") == true || acceptHeader?.contains("text/javascript") == true) {Log.d("WebView", "拦截到 JavaScript 请求: $url")
}

2. XHR 请求(XMLHttpRequest / Fetch 请求)

XHR 请求通常用于 AJAX 请求或使用 Fetch API 的异步网络请求。

判断依据:

  • URL 规则:API 请求通常有特定路径,例如 /api//ajax/ 等。
  • Acceptapplication/json(如果返回 JSON 数据)。
  • 请求头:XHR 请求会带有 X-Requested-With: XMLHttpRequest 头部(但不是所有情况都有此头部)。
if (url.contains("/api/") || acceptHeader?.contains("application/json") == true || headers["X-Requested-With"] == "XMLHttpRequest") {Log.d("WebView", "拦截到 XHR 请求: $url")
}

3. Font 请求(字体文件请求)

字体文件通常以 .woff.woff2.ttf.otf 等后缀结尾。

判断依据:

  • URL 后缀.woff.woff2.ttf.otf
  • Acceptfont/*application/font-woff
if (url.endsWith(".woff") || url.endsWith(".woff2") || url.endsWith(".ttf") || url.endsWith(".otf") || acceptHeader?.contains("font/") == true) {Log.d("WebView", "拦截到字体文件请求: $url")
}

4. PNG 请求(图片请求)

图片请求通常包括 .png.jpg.gif 等格式。

判断依据:

  • URL 后缀:图片文件通常以 .png.jpg.jpeg.gif 结尾。
  • Acceptimage/*
if (url.endsWith(".png") || url.endsWith(".jpg") || url.endsWith(".jpeg") || url.endsWith(".gif") || acceptHeader?.contains("image/") == true) {Log.d("WebView", "拦截到图片请求: $url")
}

5. Preflight 请求

Preflight 请求是 CORS 请求的一部分,通常在跨域 POST、PUT、DELETE 请求前发送,以确定服务器是否允许该请求。Preflight 请求使用 OPTIONS 方法发起。

判断依据:

  • HTTP 方法OPTIONS(Preflight 请求是 OPTIONS 方法的请求)。
  • 请求头:包含 Access-Control-Request-MethodAccess-Control-Request-Headers
if (request.method == "OPTIONS" && headers.containsKey("Access-Control-Request-Method")) {Log.d("WebView", "拦截到 Preflight 请求: $url")
}

结合 URL 和 Accept 头进行判断

总结不同请求类型的判断依据:

请求类型URL 后缀Accept其他请求头信息
Script (JavaScript).jsapplication/javascript, text/javascript
XHR (AJAX)/api/, /ajax/application/jsonX-Requested-With: XMLHttpRequest
Font (字体).woff, .woff2, .ttf, .otffont/*, application/font-woff
Image (图片).png, .jpg, .jpeg, .gifimage/*
Preflight (CORS)OPTIONS 方法,Access-Control-Request-Method

小结

  • Accept 头可以帮助判断请求类型,但并不是所有请求都明确使用它。
  • 根据 URL 后缀、请求方法、其他请求头(如 X-Requested-WithAccess-Control-Request-Method)结合判断能更准确识别不同类型的请求。

返回的响应不符合预期的格式,怎么处理

出现 AxiosError: Network Error, Code: ERR_NETWORK 错误,通常是因为 WebView 在处理拦截的网络请求时,返回的响应不符合预期的格式,或者某些必要的头信息缺失。这里有几个常见的原因及解决办法:

问题可能的原因:

  1. 响应流的格式或处理错误: 你正在返回 response.body()?.byteStream(),但是你还需要确保整个 WebResourceResponse 对象是正确配置的,尤其是内容类型、编码格式以及响应头信息。任何一项出错都可能导致 H5(例如通过 Axios)认为网络请求失败。

  2. 响应头缺失或不完整WebResourceResponse 需要提供一些关键的响应头,比如 Content-TypeContent-Length,这些头在网络请求处理中是必需的。H5 请求的 Axios 需要明确知道响应的长度和类型,否则会认为响应无效。

  3. 返回的流不完整或被提前关闭: 如果返回的流有问题,比如它被提前关闭或者有其他异常情况,可能导致 Axios 在处理时报错。

如何正确返回自定义响应

确保你使用 WebResourceResponse 构建响应时,包括了所有必要的头信息和流数据。

修改代码示例

override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest
): WebResourceResponse? {val url = request.url.toString()if (url.contains("your_api_endpoint")) {// 发起网络请求获取数据val response = fetchApiData(url)// 处理返回的响应流val byteStream = response.body?.byteStream() ?: ByteArrayInputStream(ByteArray(0))val contentType = response.header("Content-Type", "application/json") // 设置默认内容类型val contentLength = response.header("Content-Length", "-1").toLong() // 设置内容长度// 构建 WebResourceResponse 并返回给 WebViewreturn WebResourceResponse(contentType, // 内容类型"utf-8",     // 编码格式200,         // HTTP 状态码"OK",        // 状态描述mapOf(        // 响应头"Access-Control-Allow-Origin" to "*","Content-Length" to contentLength.toString()),byteStream   // 响应内容的输入流)}return super.shouldInterceptRequest(view, request)
}// 使用 OkHttp 发起网络请求
private fun fetchApiData(url: String): Response {val client = OkHttpClient()val request = Request.Builder().url(url).build()return client.newCall(request).execute() // 直接返回 Response 对象
}

关键修改点:

  1. 正确设置内容类型和编码:通过 response.header("Content-Type") 获取原始响应的 Content-Type,并传递给 WebResourceResponse。通常是 application/json

  2. 设置 Content-Length:通过 response.header("Content-Length") 获取响应内容的长度,并将其传递给 WebView。如果缺少 Content-Length,某些 H5 请求库(如 Axios)可能会报错。

  3. 返回有效的响应流:你需要确保 response.body()?.byteStream() 是有效的。如果网络请求失败或流为空,你可以返回一个空的 ByteArrayInputStream()

  4. 设置状态码和状态描述:如果请求成功,确保返回 200 OK,否则应根据具体情况返回相应的状态码和描述。

检查点

  1. 确保响应流有效:确保 response.body()?.byteStream() 真的有数据,否则 H5 端会认为是无效的响应。你可以通过调试查看响应流的状态。

  2. 正确设置头信息:特别是 Content-TypeContent-Length,它们是网络请求处理的关键。Axios 依赖这些头信息来解析响应。

  3. 错误处理:如果在网络请求过程中发生错误,应返回合适的错误响应,比如 404 Not Found500 Internal Server Error,而不是直接返回空的响应流。

调试建议

  • 通过日志调试输出 OkHttp 请求的状态,确保 fetchApiData 函数返回的 Response 对象中包含有效的数据。
  • 在 Axios 端检查返回的响应头,确保 Content-TypeContent-Length 等信息是正确的。

shouldInterceptRequest 拦截POST请求的时候,如何获取POST 请求的 body 数据?

在 Android 的 WebViewClient 中通过 shouldInterceptRequest 拦截 POST 请求并构建自定义的 HTTP 请求时,首先需要手动构建请求体(如从 WebResourceRequest 中获取必要的请求信息),然后使用 OkHttpHttpURLConnection 来发送这个 POST 请求。

WebResourceRequest 不直接提供 POST 请求体,因此要获取并手动构建 POST 请求体。这可以通过 requestHeaders 来构建,或在前端(H5)发送时提前传递 POST 数据。

处理 POST 请求并构建请求体的完整示例:

override fun shouldInterceptRequest(view: WebView,request: WebResourceRequest
): WebResourceResponse? {val url = request.url.toString()val method = request.methodif (method == "POST") {Log.d("WebView", "拦截到 POST 请求: $url")// 自定义处理 POST 请求,构建请求体并发送val responseStream = performCustomHttpPost(url, request)// 返回自定义的 WebResourceResponsereturn WebResourceResponse("application/json", // 假设返回的是 JSON 响应"UTF-8",200, // HTTP 状态码"OK", // HTTP 状态描述mapOf("Access-Control-Allow-Origin" to "*"), // 响应头responseStream // 响应数据的输入流)}return super.shouldInterceptRequest(view, request)
}// 自定义处理 POST 请求的逻辑
fun performCustomHttpPost(url: String, request: WebResourceRequest): InputStream {// 构建 POST 请求体(假设 H5 端发送的 POST 数据是 JSON 格式)val postData = getPostData(request) // 假设这里可以提取请求体数据// 日志记录请求体数据Log.d("WebView", "POST 请求数据: $postData")// 使用 OkHttp 发送自定义的 POST 请求val client = OkHttpClient()val requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), // 假设请求体是 JSON 数据postData ?: "" // POST 请求的数据)val customRequest = Request.Builder().url(url).post(requestBody).build()// 发起请求并返回响应流val response = client.newCall(customRequest).execute()Log.d("WebView", "HTTP 响应码: ${response.code()}") // 日志记录响应状态码return response.body?.byteStream() ?: ByteArrayInputStream(ByteArray(0))
}// 获取 POST 数据(需要通过前端传递或其他方式获取)
fun getPostData(request: WebResourceRequest): String? {// WebView 无法直接获取 POST body 数据,需要前端配合通过 evaluateJavascript 或其他方式传递// 假设我们从 requestHeaders 中获取部分数据(实际可以根据你的需求进行修改)val contentType = request.requestHeaders["Content-Type"]Log.d("WebView", "Content-Type: $contentType")// 这里返回模拟的 POST 数据,实际情况下需要处理真实的请求体return "{ \"key\": \"value\" }"
}
关键点:
获取请求体数据:Android WebView 本身不提供获取 POST 请求体的直接方式,需要通过前端协作(如 evaluateJavascript)来传递请求体,或者自行处理模拟请求体。手动构建 POST 请求体:使用 OkHttp 的 RequestBody.create() 方法手动构建 POST 请求体。记录日志:通过 Log.d() 记录拦截的 URL 和请求体数据,便于调试。
记录 HTTP 响应状态码,查看请求是否成功。
处理异常情况:如果响应体为空,返回一个空的 ByteArrayInputStream(),以确保 WebView 不会崩溃。关于获取真实的 POST 请求体
Android 的 WebView 没有内置机制直接获取 POST 请求体,因此需要通过 JavaScript 与 Android 通信,在 H5 端主动将 POST 数据发送给 WebView。例如:
// 在 H5 端获取 POST 请求体并传递给 Android
function sendPostDataToAndroid(data) {if (window.AndroidInterface) {window.AndroidInterface.sendPostData(JSON.stringify(data));}
}

然后在 Android 端通过 addJavascriptInterface 接收数据:

@JavascriptInterface
fun sendPostData(data: String) {// 处理从 H5 传递过来的 POST 数据Log.d("WebView", "收到的 POST 数据: $data")
}

最后

其实获取post请求体参数内容上述的方法可以尝试一下,当然,还有一种更简单的取巧的方法,如果H5 POST请求数量不是很多的话,可以和H5沟通好,直接把请求数据放在请求的url中,中间通过特定字符@隔开,然后我们拿到后进行处理,

            // 判断是否为 XHR 请求 (通过 URL 或 Accept 头判断)if ((url.contains("/api/") || acceptHeader?.contains("application/json") == true ||headers["X-Requested-With"] == "XMLHttpRequest") && !url.endsWith("html")) {LogUtils.i( "拦截到 XHR 请求: $url")// 在此可以拦截或修改 XHR 请求var respone: Response? = nullif(method == "POST"){val params = url.split("@")val test = params[0]                    // 获取 POST 请求的 body 数据val postData = URLDecoder.decode(params[1], StandardCharsets.UTF_8.toString())LogUtils.i("postData = $postData")respone = fetchApiData2(test,method,postData)}else if(method == "GET"){respone = fetchApiData(url,method,null)}val byteStream = respone?.body()?.byteStream() ?: ByteArrayInputStream(ByteArray(0))val contentType = respone?.header("Content-Type", "application/json") // 设置默认内容类型val contentLength = respone?.header("Content-Length", "-1")?.toLong() // 设置内容长度LogUtils.i("fetchApiData respone = ${respone.toString()}")return WebResourceResponse(contentType, // 内容类型"utf-8",     // 编码格式200,         // HTTP 状态码"OK",        // 状态描述mapOf(        // 响应头"Access-Control-Allow-Origin" to "*","Content-Length" to contentLength.toString()),byteStream   // 响应内容的输入流)//                return WebResourceResponse("application/json", "utf-8",respone)}
    private fun fetchApiData2(url: String, method: String, postData: String?): Response{LogUtils.i("fetchApiData2 = $url + $method + $postData")val client = UnsafeOkHttpClient.unsafeOkHttpClient.build()val requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), // 假设请求体是 JSON 数据postData ?: "" // POST 请求的数据)val requestBuilder = Request.Builder().url(url).post(requestBody).build()return client.newCall(requestBuilder).execute()}
    // 根据请求类型进行处理private fun fetchApiData(url: String, method: String, postData: Map<String, String>?): Response  {LogUtils.i("fetchApiData = $url + $method + $postData")val client = UnsafeOkHttpClient.unsafeOkHttpClient.build()val requestBuilder = Request.Builder().url(url)// 根据请求类型构建请求if (method == "POST" && postData != null) {val formBody = FormBody.Builder()postData.forEach { (key, value) -> formBody.add(key, value) }requestBuilder.post(formBody.build())}val request = requestBuilder.build()return client.newCall(request).execute() // 直接返回 Response 对象
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/880155.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TMStarget学习——T1 Segmentation数据处理及解bug

最新学习季公俊老师的神器 TMStarget 的第一个模块基于结构像的靶区计算T1 segmentation。下面上步骤&#xff1a; (1)在github 上下载 TMStarget https://github.com/jigongjun/Neuroimaging-and-Neuromodulation (2)按照要求下载依赖工具软件AFQ、vistasoft、SPM12 &#…

OpenAI o1团队突破性论文:『过程推理』中数学推理能力大幅提升,从正确中学习的新方法

原创 超 近年来&#xff0c;大型语言模型(LLMs)在复杂的多步推理任务中取得了令人瞩目的进展。这些模型能够生成逐步的思维链&#xff0c;解决从小学数学到高等微积分的各种问题。然而&#xff0c;即使是最先进的模型也常常陷入逻辑陷阱&#xff0c;产生看似合理但实际错误的推…

1.3 计算机网络的分类

欢迎大家订阅【计算机网络】学习专栏&#xff0c;开启你的计算机网络学习之旅&#xff01; 文章目录 前言一、按分布范围分类二、按传输技术分类三、按拓扑结构分类四、按使用者分类五、按传输介质分类 前言 计算机网络根据不同的标准可以被分为多种类型&#xff0c;本章从分布…

QT----基于QML的计时器

赶上了实习的末班车,现在在做QML开发,第一天的学习成果,一个计时器.逻辑挺简单的,纯QML实现,代码在仓库QT-Timer 学习使用c的listmodel 学习使用了如何用c的listmodel来存储数据. 新建一个TImeListModel类继承自QAbstractListModel class TimeListModel : public QAbstrac…

STM32CUBEIDE FreeRTOS操作教程(五):mutex互斥信号量

STM32CUBEIDE FreeRTOS操作教程&#xff08;五&#xff09;&#xff1a;mutex互斥信号量 STM32CUBE开发环境集成了STM32 HAL库进行FreeRTOS配置和开发的组件&#xff0c;不需要用户自己进行FreeRTOS的移植。这里介绍最简化的用户操作类应用教程。以STM32F401RCT6开发板为例&am…

蓝牙技术|详谈蓝牙信道探测技术,可实现厘米级精准定位

2024年9月5日&#xff0c;蓝牙技术联盟发布蓝牙6.0核心规范。相比此前各版本&#xff0c;蓝牙核心规范6.0版的主要创新和新功能包括&#xff1a;支持蓝牙信道探测、同步适配层增强、LL扩展功能和 帧空间更新。 蓝牙信道探测 市场上已经有不少高精度定位技术了&#xff0c;像 …

ToF传感器更新

我们最近改进了 ToF 解码管道&#xff08;固件&#xff09;和 ToF 工厂校准&#xff0c;该校准已应用于我们最新的带有 ToF 相机的OAK-D-SR-PoE 1. 点云 这是直接来自摄像机的原始点云&#xff08;没有应用任何后处理过滤器&#xff09;。 2. ToF 精度 &#xff08;ToF 深度误差…

界面控件Telerik UI for WinForms 2024 Q3概览 - 支持合并单元格等

Telerik UI for WinForms拥有适用Windows Forms的110多个令人惊叹的UI控件。所有的UI for WinForms控件都具有完整的主题支持&#xff0c;可以轻松地帮助开发人员在桌面和平板电脑应用程序提供一致美观的下一代用户体验。 本文将介绍界面组件Telerik UI for WinForms在今年第一…

3d可视化图片:通过原图和深度图实现

1、depthy 在线体验demo: https://depthy.stamina.pl/#/ 也可以docker安装上面服务: docker run --rm -t -i -p 9000:9000 ndahlquist/depthy http://localhost:90001)首先传原图 2)再传对应深度图 3)效果 </ifra

Linux ubuntu debian系统安装UFW防火墙图形化工具GUFW

GUFW是UFW的图形化前端&#xff0c;可以通过以下命令安装&#xff1a; sudo apt install gufw安装成功后&#xff0c;可以通过应用程序菜单启动GUFW&#xff0c;在图形界面中&#xff0c;可以方便地添加、修改和删除规则&#xff0c;查看状态和日志。

分布式系统的概念与设计模式

概念 定义&#xff1a;分布式系统是指将数据和计算任务分散到多个独立的计算机上&#xff0c;这些计算机通过网络进行通信和协作&#xff0c;共同对外提供服务。分布式系统不仅提高了系统的可靠性和可扩展性&#xff0c;还增强了系统的并发处理能力和数据管理能力。 特点&…

【操作系统强化】王道强化一轮笔记

第一章 计算机系统概述 考点1 操作系统的概念、特征和功能 1. 2. 考点2 内核态与用户态 1. 2.用户态和内核态之间的切换本质上就是应用程序和操作系统对CPU控制器的切换 考点3 中断和异常 1. 2. 考点4 系统调用 1. 2. 3.C 考点5 操作系统引导 1. 2. ①磁盘的物理格式化&…

React-Native 中使用 react-native-image-crop-picker 在华为手机上不能正常使用拍照功能

背景: React-Native 0.66 中使用 react-native-image-crop-picker 在安卓 华为手机上不能正常使用拍照功能, 其他品牌正常 代码如下: import ImagePicker from react-native-image-crop-picker;ImagePicker.openCamera(photoOptions).then(image > {callback(image);}) …

库仑定律-库仑力-两个电荷之间静电力的计算公式

图中&#xff1a; q1&#xff0c;q2 为两个电荷r 为电荷间的距离 r ^ 1 , 2 \widehat{r}_{1,2} r 1,2​ 为从 q1 指向 q2 的单位向量 F ⃗ 1 , 2 \vec{F}_{1,2} F 1,2​ 为 q1 施加到 q2 上的静电力 公式&#xff1a; F ⃗ 1 , 2 q 1 q 2 K r 2 r ^ 1 , 2 \vec{F}_{1,2} \f…

七种修复错误:由于找不到msvcr110.dll 无法继续执行的方法

当你在运行某些程序时遇到“找不到msvcr110.dll”的错误提示&#xff0c;这通常意味着你的系统缺少了Microsoft Visual C 2012 Redistributable包中的一个重要文件。这个DLL文件是Microsoft Visual C Redistributable的一部分&#xff0c;用于支持许多使用Visual C编写的软件和…

Tornado 是一个 Python 异步网络库和 web 框架

Tornado 是一个 Python 异步网络库和 web 框架&#xff0c;它最初由 FriendFeed 开发&#xff0c;后来被 Facebook 收购并开源。Tornado 因其非阻塞的 I/O 操作和优秀的性能而广受欢迎&#xff0c;特别是在需要处理大量并发连接的应用中。Tornado 的底层实现主要依赖于 Python …

【软件测试】如何设计测试用例? 设计测试用例常用的方法.

目录 一.什么是测试用例?二.总体设计测试用例的万能公式.2.1 功能性能界面兼容易用安全2.2 弱网测试2.3 安装卸载测试. 三. 常用设计具体测试用例的方法3.1 等价类3.2 边界值3.3 正交法3.3.1 正交表3.3.2 如何设计正交表,并根据正交表编写测试用例 3.4 判定表法3.4.1 根据判定…

《Nginx核心技术》第18章:基于主从模式搭建Nginx+Keepalived双机热备环境

作者&#xff1a;冰河 星球&#xff1a;http://m6z.cn/6aeFbs 博客&#xff1a;https://binghe.gitcode.host 文章汇总&#xff1a;https://binghe.gitcode.host/md/all/all.html 星球项目地址&#xff1a;https://binghe.gitcode.host/md/zsxq/introduce.html 沉淀&#xff0c…

光子架与电子架 -- 光子架与电子架

电子架 指插放交叉板、OTU单板、支/线路板、保护类单板的子架。 在通用型平台子架和平台子架中如果仅插放OTU单板&#xff08;非中继模式&#xff09;视为电子架。光电混合的子架视为电子架。 电子架主要实现将客户侧信号转换成标准波长的光信号&#xff0c;供光子架调度。 光子…

p18 docker镜像原理之联合文件系统,p19 docker镜像分层的理解

镜像是什么 镜像其实就是一种轻量级的&#xff0c;可执行的一种软件包&#xff0c;用来打包基于环境开发的软件&#xff0c;里面可以包括代码&#xff0c;环境&#xff0c;数据库&#xff0c;配置文件等信息 如何得到镜像&#xff1f; 可以从镜像仓库下载比方说dockerhub 比…