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()
方法来区分请求类型。