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;产生看似合理但实际错误的推…

只装了WPS,DOC文档无法打开

只装了WPS&#xff0c;DOC文档无法打开 打开WPS --> 全局设置 --> 设置 --> 文件格式关联 --> 与office 2007兼容 也可以选择office 2003 或 office 2010 兼容 dox文件的默认打开方式也变为WPS

1.3 计算机网络的分类

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

iostat 命令:系统状态监控

一、命令简介 ​iostat ​命令用于报告系统中 CPU、磁盘、tty 设备和 CPU 利用率统计信息。 ‍ 需安装 sysstat ​软件包&#xff0c;该软件包提供了一组工具&#xff0c;包括 iostat​、sar​、mpstat ​等&#xff0c;用于系统性能监控和报告。 ‍ 二、命令参数 iostat…

STM32 MPU加速效果测试

测试代码&#xff1a; static volatile uint32_t cnt;cnt 0;uint64_t time time_spent({while (cnt < 1000000){cnt;}});log_info("test time spent: %llu us\r\n", time); 结果&#xff1a; //未开启Cache fmc_ram test: uint32_t spent time: 955963 us uin…

STM32之串口通信

什么是串口 串行通信接口&#xff1a;指按位发送和接收的接口&#xff0c;如RS232/422/485 RS232电平和COMS/TTL电平对比 RS232电平&#xff1a;逻辑1&#xff1a;-15V ~ -3V 逻辑0:3V ~ 15V CMOS电平: 逻辑1&#xff1a;3.3V 逻辑0&#xff1a;0V &#xff08;STM32使用&am…

服务注册中心对比及使用场景分析

目录 引言服务注册中心简介注册中心对比 1. Consul 1.1 介绍1.2 特性1.3 使用场景1.4 AP vs CP 2. Nacos 2.1 介绍2.2 特性2.3 使用场景2.4 AP vs CP 3. ZooKeeper 3.1 介绍3.2 特性3.3 使用场景3.4 AP vs CP 对比表格选择建议总结 引言 随着微服务架构的普及&#xff0c;服…

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

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

前端大屏自适应方案

一般后台管理页面&#xff0c;需要自适应的也就是大屏这一个&#xff0c;其他的尺寸我感觉用第三方框架继承好的就挺合适的&#xff0c;当然自适应方案也可以同步到所有页面&#xff0c;但我感觉除了 to c 的项目&#xff0c;不太需要所有页面自适应&#xff0c;毕竟都是查看和…

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

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

通过http地址下载文件

1.HttpWebResponse方法 public void GetPostContent(string url, string localSavePath) {try{ServicePointManager.SecurityProtocol SecurityProtocolType.Tls12;HttpWebRequest myRequest (HttpWebRequest)WebRequest.Create(url);myRequest.Method "GET";myR…

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

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在今年第一…

PostgreSQL 模式

PostgreSQL 模式 介绍 PostgreSQL 是一种功能强大的开源对象关系数据库管理系统&#xff08;ORDBMS&#xff09;&#xff0c;它以其可靠性、健壮性和支持高级功能而闻名。在 PostgreSQL 中&#xff0c;模式&#xff08;schema&#xff09;是一个重要的概念&#xff0c;它用于…

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;查看状态和日志。

如何在Windows上安装Docker

在 Windows 上使用 Docker 有两种主要方式&#xff1a;通过 Docker Desktop 安装并使用 WSL 2 作为后端&#xff0c;或者直接在 WSL 2 中安装 Docker。这里推荐手残党直接用图形界面安装到WSL 2的后端&#xff1a; 一、启用Hyper-V和容器特性 1. 右键Windows点击应用和功能 …

【ppt2svg svg2png/jpg】ppt转图片解决方案

ppt处理工具 pptx 免费&#xff0c;功能有限&#xff0c;会有一些问题aspose 收费&#xff0c;功能丰富&#xff0c;有水印spire 收费&#xff0c;功能丰富&#xff0c;有水印基于js/vue的方案 任务&#xff1a;PPT转图片 为了跳过水印&#xff0c;有几种间接的方案 方案一 …