欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android?webview攔截H5的接口請求并返回處理好的數(shù)據(jù)代碼示例

 更新時間:2024年10月14日 08:33:22   作者:大漁歌_  
這篇文章主要給大家介紹了關于Android?webview攔截H5的接口請求并返回處理好的數(shù)據(jù)的相關資料,通過WebView的shouldInterceptRequest方法,Android可以攔截并處理WebView中的H5網(wǎng)絡請求,需要的朋友可以參考下

Android webview攔截H5的接口請求并返回處理好的數(shù)據(jù)

Android 可以通過 WebView 的 shouldInterceptRequest 方法攔截到 H5 中的網(wǎng)絡請求。這是一個 WebViewClient 中的回調方法,允許開發(fā)者在 WebView 發(fā)起網(wǎng)絡請求時對其進行處理和修改。

具體使用方法如下:

  • 你需要創(chuàng)建一個自定義的 WebViewClient,并重寫 shouldInterceptRequest 方法。

  • 在該方法中,你可以攔截 WebView 發(fā)起的網(wǎng)絡請求,并返回一個自定義的響應,或讓請求繼續(xù)。

  • 該方法在 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,并根據(jù)需要攔截或修改請求
        if (url.contains("your_target_url")) {
            // 可以在這里做一些處理,例如替換請求或返回本地數(shù)據(jù)
            val inputStream = ... // 自定義輸入流
            return WebResourceResponse("text/html", "UTF-8", inputStream)
        }
        // 不攔截,繼續(xù)請求
        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 對象,來改變或替換原始的網(wǎng)絡請求,也可以通過默認實現(xiàn)讓請求繼續(xù)執(zhí)行。

獲取網(wǎng)絡接口請求的數(shù)據(jù)(如 API 請求的響應),然后將其返回給 H5,

有以下幾種方式可以考慮:

1. 攔截請求并手動發(fā)起請求

你可以通過 shouldInterceptRequest 方法攔截 WebView 的 API 請求,自己在 Java 或 Kotlin 中使用 HttpURLConnection 或 OkHttp 發(fā)起網(wǎng)絡請求,處理完響應后,再將響應數(shù)據(jù)傳遞給 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 發(fā)起請求
            val response = fetchApiData(url)

            // 將獲取的響應內(nèi)容傳遞給 H5
            view.post {
                view.evaluateJavascript("javascript:handleApiResponse('${response}')", null)
            }

            // 返回一個空響應或自定義內(nèi)容
            return WebResourceResponse("application/json", "UTF-8", null)
        }

        return super.shouldInterceptRequest(view, request)
    }

    // 使用 OkHttp 發(fā)起網(wǎng)絡請求(可以根據(jù)你的需求選擇合適的網(wǎng)絡庫)
    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 會攔截指定的網(wǎng)絡請求,然后用 OkHttp 發(fā)起請求,并將獲取的響應數(shù)據(jù)通過 evaluateJavascript 方法傳回到 WebView 中的 H5 頁面。

2. 通過 WebView 和 H5 的 JavaScript 通信

另一種方式是通過 WebView 的 addJavascriptInterface 方法,將 Android 代碼和 H5 進行通信。當 Android 發(fā)起請求后,可以通過接口將數(shù)據(jù)傳遞給 H5。

在 H5 中定義一個 JavaScript 函數(shù),用于接收數(shù)據(jù):

function handleApiResponse(response) {
    console.log("API Response: ", response);
    // 這里可以對響應進行處理,渲染到頁面等
}

在 Android 端:

webView.addJavascriptInterface(object {
    @JavascriptInterface
    fun sendDataToH5(data: String) {
        // 發(fā)送數(shù)據(jù)到 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 接口傳遞數(shù)據(jù)到 H5
            view.post {
                view.evaluateJavascript("javascript:AndroidInterface.sendDataToH5('${response}')", null)
            }
            
            return WebResourceResponse("application/json", "UTF-8", null)
        }
        return super.shouldInterceptRequest(view, request)
    }
}

這種需要考慮到H5 發(fā)過來的網(wǎng)絡接口請求類型嗎?post 還是 get

是的,在使用 shouldInterceptRequest 攔截 H5 發(fā)過來的網(wǎng)絡請求時,需要考慮請求的類型(GET 或 POST)。這是因為 GET 和 POST 請求的處理方式不同,尤其是 POST 請求,它帶有請求體(body)數(shù)據(jù),而 GET 請求通常只包含 URL 參數(shù)。

shouldInterceptRequest 可以幫助你攔截請求,但對于 POST 請求的處理,需要特別注意提取和使用請求體。

如何區(qū)分 GET 和 POST 請求?

在 API 21 及更高版本中,shouldInterceptRequest 方法中的 WebResourceRequest 對象包含了更多信息,可以通過它的 getMethod() 方法來區(qū)分請求類型。

override fun shouldInterceptRequest(
    view: WebView, 
    request: WebResourceRequest
): WebResourceResponse? {
    val url = request.url.toString()
    val method = request.method  // 獲取請求方法,如 GET 或 POST

    // 根據(jù)請求類型處理
    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 請求數(shù)據(jù)

你可以讓 H5 頁面在發(fā)出 POST 請求前,通過 JavaScript 提前將 POST 請求的數(shù)據(jù)發(fā)送到 WebView。然后 Android 端可以攔截并處理這些數(shù)據(jù)。

  • 在 H5 中攔截和傳遞 POST 請求數(shù)據(jù):

    function interceptAndSendPostData(url, data) {
        // 調用 Android 接口,將數(shù)據(jù)傳遞給 WebView
        AndroidInterface.sendPostData(url, JSON.stringify(data));
        
        // 繼續(xù)發(fā)起 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 數(shù)據(jù):

    webView.addJavascriptInterface(object {
        @JavascriptInterface
        fun sendPostData(url: String, data: String) {
            // 這里可以處理傳遞過來的 POST 請求數(shù)據(jù)
            Log.d("WebView", "POST 請求 URL: $url, 數(shù)據(jù): $data")
        }
    }, "AndroidInterface")
    

方法 2:通過自定義網(wǎng)絡層發(fā)送 POST 請求

另一種方式是在 shouldInterceptRequest 中攔截 POST 請求后,手動發(fā)起 HTTP 請求,處理請求體和響應數(shù)據(jù)。雖然 shouldInterceptRequest 本身不直接提供請求體,但你可以在 H5 頁面中通過 JavaScript 提前將 POST 請求體傳遞給 Android,或者通過其他網(wǎng)絡攔截方式處理(例如使用 OkHttp 的攔截器)。

override fun shouldInterceptRequest(
    view: WebView, 
    request: WebResourceRequest
): WebResourceResponse? {
    val url = request.url.toString()
    val method = request.method  // 獲取請求方法,如 GET 或 POST

    if (method == "POST") {
        // 自定義發(fā)起 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 發(fā)送自定義 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 請求:需要特別處理請求體數(shù)據(jù)。你可以通過 JavaScript 提前將 POST 請求數(shù)據(jù)傳遞給 WebView,或通過手動發(fā)起 HTTP 請求處理 POST 請求及其響應。

shouldInterceptRequest 能判斷出來網(wǎng)絡請求的類型嗎?比如script xhr 等

shouldInterceptRequest 本身并不能直接判斷網(wǎng)絡請求的具體類型(如 script、xhr 等),因為它沒有提供一個字段明確表明請求是某種類型的資源(如 JavaScript 文件、XHR 請求等)。不過,你可以通過請求的 URL 和 請求頭信息 來推斷請求的類型。

在 API 21 及以上的 Android 版本中,WebResourceRequest 對象提供了豐富的信息,包括請求的 URL、請求方法(GET、POST 等)、請求頭等,可以根據(jù)這些信息推斷請求類型。

如何通過 URL 和請求頭判斷請求類型?

  • 通過 URL 后綴

    • 如果請求的 URL 以 .js 結尾,通常可以認為這是一個 script 請求。
    • 如果 URL 中包含 /api/ 或類似的標識符,可能是 xhr 請求。
    • CSS 通常以 .css 結尾,圖片文件以 .jpg、.png.gif 結尾等。
  • 通過請求頭: 你可以通過請求的頭部來推斷請求的類型,例如 Accept 頭部通常指示客戶端期望接收到的數(shù)據(jù)類型。

    • 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 規(guī)則判斷:如果 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 請求中指示客戶端希望接收的響應數(shù)據(jù)類型,它確實能在一些情況下幫助我們判斷請求的資源類型。但并不是所有類型的請求都會明確使用 Accept 頭。因此,我們需要結合 URL 和 請求頭 的其他信息(如 Content-Type、Access-Control-Request-Method 等)來進行判斷。

1. Script(JavaScript 請求)

JavaScript 請求是用來加載 .js 文件的資源請求。

判斷依據(jù):

  • 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 的異步網(wǎng)絡請求。

判斷依據(jù):

  • URL 規(guī)則:API 請求通常有特定路徑,例如 /api/、/ajax/ 等。
  • Accept 頭:application/json(如果返回 JSON 數(shù)據(jù))。
  • 請求頭: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 等后綴結尾。

判斷依據(jù):

  • 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 等格式。

判斷依據(jù):

  • 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 請求前發(fā)送,以確定服務器是否允許該請求。Preflight 請求使用 OPTIONS 方法發(fā)起。

判斷依據(jù):

  • 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 頭進行判斷

總結不同請求類型的判斷依據(jù):

請求類型URL 后綴Accept 頭其他請求頭信息
Script (JavaScript).jsapplication/javascripttext/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 頭可以幫助判斷請求類型,但并不是所有請求都明確使用它。
  • 根據(jù) URL 后綴、請求方法、其他請求頭(如 X-Requested-With、Access-Control-Request-Method)結合判斷能更準確識別不同類型的請求。

返回的響應不符合預期的格式,怎么處理

出現(xiàn) AxiosError: Network Error, Code: ERR_NETWORK 錯誤,通常是因為 WebView 在處理攔截的網(wǎng)絡請求時,返回的響應不符合預期的格式,或者某些必要的頭信息缺失。這里有幾個常見的原因及解決辦法:

問題可能的原因:

  • 響應流的格式或處理錯誤: 你正在返回 response.body()?.byteStream(),但是你還需要確保整個 WebResourceResponse 對象是正確配置的,尤其是內(nèi)容類型、編碼格式以及響應頭信息。任何一項出錯都可能導致 H5(例如通過 Axios)認為網(wǎng)絡請求失敗。

  • 響應頭缺失或不完整: WebResourceResponse 需要提供一些關鍵的響應頭,比如 Content-Type 和 Content-Length,這些頭在網(wǎng)絡請求處理中是必需的。H5 請求的 Axios 需要明確知道響應的長度和類型,否則會認為響應無效。

  • 返回的流不完整或被提前關閉: 如果返回的流有問題,比如它被提前關閉或者有其他異常情況,可能導致 Axios 在處理時報錯。

如何正確返回自定義響應

確保你使用 WebResourceResponse 構建響應時,包括了所有必要的頭信息和流數(shù)據(jù)。

修改代碼示例

override fun shouldInterceptRequest(
    view: WebView, 
    request: WebResourceRequest
): WebResourceResponse? {
    val url = request.url.toString()
    
    if (url.contains("your_api_endpoint")) {
        // 發(fā)起網(wǎng)絡請求獲取數(shù)據(jù)
        val response = fetchApiData(url)
        
        // 處理返回的響應流
        val byteStream = response.body?.byteStream() ?: ByteArrayInputStream(ByteArray(0))
        val contentType = response.header("Content-Type", "application/json") // 設置默認內(nèi)容類型
        val contentLength = response.header("Content-Length", "-1").toLong() // 設置內(nèi)容長度
        
        // 構建 WebResourceResponse 并返回給 WebView
        return WebResourceResponse(
            contentType, // 內(nèi)容類型
            "utf-8",     // 編碼格式
            200,         // HTTP 狀態(tài)碼
            "OK",        // 狀態(tài)描述
            mapOf(        // 響應頭
                "Access-Control-Allow-Origin" to "*",
                "Content-Length" to contentLength.toString()
            ),
            byteStream   // 響應內(nèi)容的輸入流
        )
    }

    return super.shouldInterceptRequest(view, request)
}

// 使用 OkHttp 發(fā)起網(wǎng)絡請求
private fun fetchApiData(url: String): Response {
    val client = OkHttpClient()
    val request = Request.Builder().url(url).build()

    return client.newCall(request).execute() // 直接返回 Response 對象
}

關鍵修改點:

  • 正確設置內(nèi)容類型和編碼:通過 response.header("Content-Type") 獲取原始響應的 Content-Type,并傳遞給 WebResourceResponse。通常是 application/json

  • 設置 Content-Length:通過 response.header("Content-Length") 獲取響應內(nèi)容的長度,并將其傳遞給 WebView。如果缺少 Content-Length,某些 H5 請求庫(如 Axios)可能會報錯。

  • 返回有效的響應流:你需要確保 response.body()?.byteStream() 是有效的。如果網(wǎng)絡請求失敗或流為空,你可以返回一個空的 ByteArrayInputStream()。

  • 設置狀態(tài)碼和狀態(tài)描述:如果請求成功,確保返回 200 OK,否則應根據(jù)具體情況返回相應的狀態(tài)碼和描述。

檢查點

  • 確保響應流有效:確保 response.body()?.byteStream() 真的有數(shù)據(jù),否則 H5 端會認為是無效的響應。你可以通過調試查看響應流的狀態(tài)。

  • 正確設置頭信息:特別是 Content-Type 和 Content-Length,它們是網(wǎng)絡請求處理的關鍵。Axios 依賴這些頭信息來解析響應。

  • 錯誤處理:如果在網(wǎng)絡請求過程中發(fā)生錯誤,應返回合適的錯誤響應,比如 404 Not Found 或 500 Internal Server Error,而不是直接返回空的響應流。

調試建議

  • 通過日志調試輸出 OkHttp 請求的狀態(tài),確保 fetchApiData 函數(shù)返回的 Response 對象中包含有效的數(shù)據(jù)。
  • 在 Axios 端檢查返回的響應頭,確保 Content-TypeContent-Length 等信息是正確的。

shouldInterceptRequest 攔截POST請求的時候,如何獲取POST 請求的 body 數(shù)據(jù)?

在 Android 的 WebViewClient 中通過 shouldInterceptRequest 攔截 POST 請求并構建自定義的 HTTP 請求時,首先需要手動構建請求體(如從 WebResourceRequest 中獲取必要的請求信息),然后使用 OkHttp 或 HttpURLConnection 來發(fā)送這個 POST 請求。

WebResourceRequest 不直接提供 POST 請求體,因此要獲取并手動構建 POST 請求體。這可以通過 requestHeaders 來構建,或在前端(H5)發(fā)送時提前傳遞 POST 數(shù)據(jù)。

處理 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 請求,構建請求體并發(fā)送
        val responseStream = performCustomHttpPost(url, request)

        // 返回自定義的 WebResourceResponse
        return WebResourceResponse(
            "application/json", // 假設返回的是 JSON 響應
            "UTF-8",
            200, // HTTP 狀態(tài)碼
            "OK", // HTTP 狀態(tài)描述
            mapOf("Access-Control-Allow-Origin" to "*"), // 響應頭
            responseStream // 響應數(shù)據(jù)的輸入流
        )
    }

    return super.shouldInterceptRequest(view, request)
}

// 自定義處理 POST 請求的邏輯
fun performCustomHttpPost(url: String, request: WebResourceRequest): InputStream {
    // 構建 POST 請求體(假設 H5 端發(fā)送的 POST 數(shù)據(jù)是 JSON 格式)
    val postData = getPostData(request) // 假設這里可以提取請求體數(shù)據(jù)

    // 日志記錄請求體數(shù)據(jù)
    Log.d("WebView", "POST 請求數(shù)據(jù): $postData")

    // 使用 OkHttp 發(fā)送自定義的 POST 請求
    val client = OkHttpClient()
    val requestBody = RequestBody.create(
        MediaType.parse("application/json; charset=utf-8"), // 假設請求體是 JSON 數(shù)據(jù)
        postData ?: "" // POST 請求的數(shù)據(jù)
    )

    val customRequest = Request.Builder()
        .url(url)
        .post(requestBody)
        .build()

    // 發(fā)起請求并返回響應流
    val response = client.newCall(customRequest).execute()

    Log.d("WebView", "HTTP 響應碼: ${response.code()}") // 日志記錄響應狀態(tài)碼

    return response.body?.byteStream() ?: ByteArrayInputStream(ByteArray(0))
}

// 獲取 POST 數(shù)據(jù)(需要通過前端傳遞或其他方式獲?。?
fun getPostData(request: WebResourceRequest): String? {
    // WebView 無法直接獲取 POST body 數(shù)據(jù),需要前端配合通過 evaluateJavascript 或其他方式傳遞
    // 假設我們從 requestHeaders 中獲取部分數(shù)據(jù)(實際可以根據(jù)你的需求進行修改)
    val contentType = request.requestHeaders["Content-Type"]
    Log.d("WebView", "Content-Type: $contentType")

    // 這里返回模擬的 POST 數(shù)據(jù),實際情況下需要處理真實的請求體
    return "{ \"key\": \"value\" }"
}
關鍵點:
獲取請求體數(shù)據(jù):Android WebView 本身不提供獲取 POST 請求體的直接方式,需要通過前端協(xié)作(如 evaluateJavascript)來傳遞請求體,或者自行處理模擬請求體。

手動構建 POST 請求體:使用 OkHttp 的 RequestBody.create() 方法手動構建 POST 請求體。

記錄日志:

通過 Log.d() 記錄攔截的 URL 和請求體數(shù)據(jù),便于調試。
記錄 HTTP 響應狀態(tài)碼,查看請求是否成功。
處理異常情況:如果響應體為空,返回一個空的 ByteArrayInputStream(),以確保 WebView 不會崩潰。

關于獲取真實的 POST 請求體
Android 的 WebView 沒有內(nèi)置機制直接獲取 POST 請求體,因此需要通過 JavaScript 與 Android 通信,在 H5 端主動將 POST 數(shù)據(jù)發(fā)送給 WebView。例如:
// 在 H5 端獲取 POST 請求體并傳遞給 Android
function sendPostDataToAndroid(data) {
    if (window.AndroidInterface) {
        window.AndroidInterface.sendPostData(JSON.stringify(data));
    }
}

然后在 Android 端通過 addJavascriptInterface 接收數(shù)據(jù):

@JavascriptInterface
fun sendPostData(data: String) {
    // 處理從 H5 傳遞過來的 POST 數(shù)據(jù)
    Log.d("WebView", "收到的 POST 數(shù)據(jù): $data")
}

最后

其實獲取post請求體參數(shù)內(nèi)容上述的方法可以嘗試一下,當然,還有一種更簡單的取巧的方法,如果H5 POST請求數(shù)量不是很多的話,可以和H5溝通好,直接把請求數(shù)據(jù)放在請求的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 數(shù)據(jù)
                    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") // 設置默認內(nèi)容類型
                val contentLength = respone?.header("Content-Length", "-1")?.toLong() // 設置內(nèi)容長度

                LogUtils.i("fetchApiData respone = ${respone.toString()}")
                return WebResourceResponse(
                    contentType, // 內(nèi)容類型
                    "utf-8",     // 編碼格式
                    200,         // HTTP 狀態(tài)碼
                    "OK",        // 狀態(tài)描述
                    mapOf(        // 響應頭
                        "Access-Control-Allow-Origin" to "*",
                        "Content-Length" to contentLength.toString()
                    ),
                    byteStream   // 響應內(nèi)容的輸入流
                )

//                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 數(shù)據(jù)
            postData ?: "" // POST 請求的數(shù)據(jù)
        )
        val requestBuilder = Request.Builder()
            .url(url)
            .post(requestBody)
            .build()

        return client.newCall(requestBuilder).execute()
    }
    // 根據(jù)請求類型進行處理
    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)

        // 根據(jù)請求類型構建請求
        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 對象
}

總結 

到此這篇關于Android webview攔截H5的接口請求并返回處理好的數(shù)據(jù)的文章就介紹到這了,更多相關Android webview攔截H5接口請求內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關文章

最新評論