马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
Android webview拦截H5的接口哀求并返回处置处罚好的数据
Android 可以通过 WebView 的 shouldInterceptRequest 方法拦截到 H5 中的网络哀求。这是一个 WebViewClient 中的回调方法,答应开发者在 WebView 发起网络哀求时对其举行处置处罚和修改。
具体利用方法如下:
- 你必要创建一个自界说的 WebViewClient,并重写 shouldInterceptRequest 方法。
- 在该方法中,你可以拦截 WebView 发起的网络哀求,并返回一个自界说的响应,或让哀求继续。
- 该方法在 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 中利用 HttpURLConnection 或 OkHttp 发起网络哀求,处置处罚完响应后,再将响应数据通报给 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)
- // 将获取的响应内容传递给 H5
- view.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。
- 在 H5 中界说一个 JavaScript 函数,用于接收数据:
- function handleApiResponse(response) {
- console.log("API Response: ", response);
- // 这里可以对响应进行处理,渲染到页面等
- }
复制代码 2. 在 Android 端:
- webView.addJavascriptInterface(object {
- @JavascriptInterface
- fun sendDataToH5(data: String) {
- // 发送数据到 H5
- webView.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 接口传递数据到 H5
- view.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 端可以拦截并处置处罚这些数据。
- 在 H5 中拦截和通报 POST 哀求数据:
- function interceptAndSendPostData(url, data) {
- // 调用 Android 接口,将数据传递给 WebView
- AndroidInterface.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));
- }
复制代码 - 在 Android 中接收 POST 数据:
- webView.addJavascriptInterface(object {
- @JavascriptInterface
- fun 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 或 POST
- if (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 本身并不能直接判断网络哀求的具体类型(如 script、xhr 等),由于它没有提供一个字段明确表明哀求是某种类型的资源(如 JavaScript 文件、XHR 哀求等)。不过,你可以通过哀求的 URL 和 哀求头信息 来推断哀求的类型。
在 API 21 及以上的 Android 版本中,WebResourceRequest 对象提供了丰富的信息,包罗哀求的 URL、哀求方法(GET、POST 等)、哀求头等,可以根据这些信息推断哀求类型。
如何通过 URL 和哀求头判断哀求类型?
- 通过 URL 后缀:
- 假如哀求的 URL 以 .js 结尾,通常可以以为这是一个 script 哀求。
- 假如 URL 中包含 /api/ 或类似的标识符,可能是 xhr 哀求。
- CSS 通常以 .css 结尾,图片文件以 .jpg、.png、.gif 结尾等。
- 通过哀求头: 你可以通过哀求的头部来推断哀求的类型,比方 Accept 头部通常指示客户端期望接收到的数据类型。
- Accept: application/json 常用于 xhr 哀求。
- Accept: text/css 表示哀求 CSS 文件。
- Accept: application/javascript 或 Accept: text/javascript 用于 JavaScript 文件哀求。
代码示例:如何通过 URL 和哀求头推断哀求类型
- override fun shouldInterceptRequest(
- view: WebView,
- request: WebResourceRequest
- ): WebResourceResponse? {
- val url = request.url.toString()
- val headers = request.requestHeaders
- val 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/javascript 或 text/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 页面哀求:
小结
固然 shouldInterceptRequest 没有直接提供资源类型的字段,但你可以通过 URL 的格式和哀求头(特别是 Accept 头)来推断哀求的类型,从而拦截特定的资源哀求。
script xhr font png preflight 分别是什么,应该怎么判断呢?都可以通过 val acceptHeader = headers["Accept"] 来举行判断吗?
Accept 头在 HTTP 哀求中指示客户端盼望接收的响应数据类型,它确实能在一些情况下帮助我们判断哀求的资源类型。但并不是所有类型的哀求都会明确利用 Accept 头。因此,我们必要结合 URL 和 哀求头 的其他信息(如 Content-Type、Access-Control-Request-Method 等)来举行判断。
1. Script(JavaScript 哀求)
JavaScript 哀求是用来加载 .js 文件的资源哀求。
判断依据:
- URL 后缀:通常 .js 文件后缀。
- Accept 头:application/javascript 或 text/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/ 等。
- Accept 头:application/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。
- Accept 头:font/* 或 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 结尾。
- Accept 头:image/*。
- 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-Method 和 Access-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/javascriptXHR (AJAX)/api/, /ajax/application/jsonX-Requested-With: XMLHttpRequestFont (字体).woff, .woff2, .ttf, .otffont/*, application/font-woffImage (图片).png, .jpg, .jpeg, .gifimage/*Preflight (CORS)OPTIONS 方法,Access-Control-Request-Method 小结
- Accept 头可以帮助判断哀求类型,但并不是所有哀求都明确利用它。
- 根据 URL 后缀、哀求方法、其他哀求头(如 X-Requested-With、Access-Control-Request-Method)结合判断能更准确辨认不同类型的哀求。
返回的响应不符合预期的格式,怎么处置处罚
出现 AxiosError: Network Error, Code: ERR_NETWORK 错误,通常是由于 WebView 在处置处罚拦截的网络哀求时,返回的响应不符合预期的格式,或者某些必要的头信息缺失。这里有几个常见的原因及解决办法:
问题可能的原因:
- 响应流的格式或处置处罚错误: 你正在返回 response.body()?.byteStream(),但是你还必要确保整个 WebResourceResponse 对象是准确设置的,尤其是内容类型、编码格式以及响应头信息。任何一项堕落都可能导致 H5(比方通过 Axios)以为网络哀求失败。
- 响应头缺失或不完备: WebResourceResponse 必要提供一些关键的响应头,好比 Content-Type 和 Content-Length,这些头在网络哀求处置处罚中是必须的。H5 哀求的 Axios 必要明确知道响应的长度和类型,否则会以为响应无效。
- 返回的流不完备或被提前关闭: 假如返回的流有问题,好比它被提前关闭或者有其他异常情况,可能导致 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 并返回给 WebView
- return 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 对象
- }
复制代码 关键修改点:
- 准确设置内容类型和编码:通过 response.header("Content-Type") 获取原始响应的 Content-Type,并通报给 WebResourceResponse。通常是 application/json。
- 设置 Content-Length:通过 response.header("Content-Length") 获取响应内容的长度,并将其通报给 WebView。假如缺少 Content-Length,某些 H5 哀求库(如 Axios)可能会报错。
- 返回有用的响应流:你必要确保 response.body()?.byteStream() 是有用的。假如网络哀求失败或流为空,你可以返回一个空的 ByteArrayInputStream()。
- 设置状态码和状态形貌:假如哀求乐成,确保返回 200 OK,否则应根据具体情况返回相应的状态码和形貌。
检查点
- 确保响应流有用:确保 response.body()?.byteStream() 真的有数据,否则 H5 端会以为是无效的响应。你可以通过调试查看响应流的状态。
- 准确设置头信息:特别是 Content-Type 和 Content-Length,它们是网络哀求处置处罚的关键。Axios 依赖这些头信息来解析响应。
- 错误处置处罚:假如在网络哀求过程中发生错误,应返回合适的错误响应,好比 404 Not Found 或 500 Internal Server Error,而不是直接返回空的响应流。
调试发起
- 通过日志调试输出 OkHttp 哀求的状态,确保 fetchApiData 函数返回的 Response 对象中包含有用的数据。
- 在 Axios 端检查返回的响应头,确保 Content-Type、Content-Length 等信息是准确的。
shouldInterceptRequest 拦截POST哀求的时候,如何获取POST 哀求的 body 数据?
在 Android 的 WebViewClient 中通过 shouldInterceptRequest 拦截 POST 哀求并构建自界说的 HTTP 哀求时,起首必要手动构建哀求体(如从 WebResourceRequest 中获取必要的哀求信息),然后利用 OkHttp 或 HttpURLConnection 来发送这个 POST 哀求。
WebResourceRequest 不直接提供 POST 哀求体,因此要获取并手动构建 POST 哀求体。这可以通过 requestHeaders 来构建,或在前端(H5)发送时提前通报 POST 数据。
处置处罚 POST 哀求并构建哀求体的完备示例:
- override fun shouldInterceptRequest(
- view: WebView,
- request: WebResourceRequest
- ): WebResourceResponse? {
- val url = request.url.toString()
- val method = request.method
- if (method == "POST") {
- Log.d("WebView", "拦截到 POST 请求: $url")
- // 自定义处理 POST 请求,构建请求体并发送
- val responseStream = performCustomHttpPost(url, request)
- // 返回自定义的 WebResourceResponse
- return 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? = null
- if(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 对象
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |