Này các bạn developer ơi, đã bao giờ bạn tự hỏi làm sao để "can thiệp" vào MỌI yêu cầu mạng mà WebView của bạn gửi đi trên cả Android lẫn iOS chưa? Nghe có vẻ phức tạp như nhiệm vụ của điệp viên 007 ấy nhỉ? Nhưng tin vui là: KHÔNG HỀ KHÓ CHÚT NÀO đâu! Hôm nay, mình sẽ bật mí cho bạn cách làm chủ những yêu cầu "bí mật" này, từ A đến Z, trên cả hai nền tảng nhé!<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/network_interception_concept.png' alt='Minh họa chặn yêu cầu mạng'>Phần 1: Android - Dễ như ăn kẹo!Ở Android, việc này thực sự dễ dàng đến bất ngờ! Bạn chỉ cần tạo một WebViewClient tùy chỉnh và "ghi đè" (override) lên hàm shouldInterceptRequest. Tưởng tượng thế này, hàm này chính là "người gác cổng" thông minh của WebView đó. Mỗi khi có một yêu cầu mạng được gửi đi, người gác cổng này sẽ "chặn lại" và hỏi bạn: "Này, tôi có nên cho yêu cầu này đi tiếp không, hay là chặn nó lại đây?".Code sẽ trông "cool" như thế này nè:```kotlinWebView(context).apply { // ... một vài cài đặt khác webViewClient = object : WebViewClientCompat() { override fun shouldInterceptRequest( view: WebView, request: WebResourceRequest, ): WebResourceResponse? { val requestHost = request.url.host // Lấy tên miền của yêu cầu val isRequestAllowed = allowedHostsList.entries.any { it.host == requestHost } // Kiểm tra xem tên miền này có trong danh sách cho phép không if (isRequestAllowed) { // Nếu được phép, cứ cho qua bình thường nhé! // Bạn có thể trả về null hoặc gọi super.shouldInterceptRequest(view, request) return null } // Aww, không được phép! Chặn đứng ngay lập tức! // Chúng ta gửi về một phản hồi lỗi 403 (Forbidden) return WebResourceResponse("text/html", "utf-8", 403, "Blocked", emptyMap(), ByteArrayInputStream(ByteArray(0))) } } // ... tiếp tục cài đặt}```Thấy chưa? Với phương pháp này, bạn có thể hoàn toàn kiểm soát và xử lý các yêu cầu mạng theo ý muốn. Một điều cần lưu ý nhỏ là request.url.host chỉ chứa tên miền (ví dụ: google.com), không có đường dẫn hay giao thức (như https://). Nếu bạn muốn lấy toàn bộ thông tin URL, hãy dùng đối tượng request.url nhé!<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/android_webview_intercept.png' alt='Quy trình chặn yêu cầu WebView trên Android'>Phần 2: iOS - Một "mánh khóe" nhỏ nhưng hiệu quả!Giờ thì sang iOS, mọi chuyện có hơi "khó nhằn" một chút, vì Apple không cho mình "chặn đứng" request một cách trực tiếp như Android đâu. Bạn có thể can thiệp vào các yêu cầu điều hướng (khi người dùng click vào link chuyển trang) bằng WKNavigationDelegate, nhưng những request được tạo ra từ JavaScript trên trang web thì chịu bó tay!Nhưng đừng lo, "anh hùng cứu tinh" của chúng ta đây rồi: WKContentRuleList! Nghe tên hơi "hàn lâm" chút, nhưng thực chất nó hoạt động giống hệt như các "trình chặn nội dung" (content blockers) mà bạn vẫn dùng trên Safari vậy đó. Về cơ bản, nó là một danh sách các quy tắc giúp bạn "lọc" và chặn các yêu cầu đến các URL cụ thể.Và đây là "mánh khóe" siêu cấp: Chúng ta sẽ chặn... TẤT CẢ mọi thứ trước, sau đó mới "châm chước" cho phép những tên miền mình muốn! (Đúng là trick mà, phải không?).Đầu tiên, bạn cần định nghĩa danh sách quy tắc này dưới dạng một mảng JSON:```json[{ "trigger": { "url-filter": ".*" // Chặn tất cả mọi URL (dùng regex ".*" cho "khô máu") }, "action": { "type": "block" // Hành động: Chặn! } },{ "trigger": { "url-filter": "google.com" // Riêng với google.com thì khác nhé! }, "action": { "type": "ignore-previous-rules" // Hành động: Bỏ qua các quy tắc chặn trước đó (cho phép đi qua) }}]```Nhìn vào cấu trúc, bạn thấy đơn giản không? Mỗi quy tắc có trigger (kích hoạt) và action (hành động). url-filter trong trigger cho phép bạn dùng regex để khớp với URL. Còn type trong action sẽ quyết định chuyện gì xảy ra.Trong ví dụ trên, chúng ta "khai báo" rằng: "À, ban đầu cứ chặn hết đi đã (với url-filter: ".*" và type: "block"). Nhưng nếu gặp google.com thì hãy "bỏ qua các quy tắc cũ" (type: "ignore-previous-rules") để cho nó đi qua nhé!".Sau khi đã có "danh sách đen/trắng" này, bạn cần biên dịch nó và thêm vào userContentController của WebView:```swiftlet contentRulesList = """[ { "trigger": { "url-filter": ".*" }, "action": { "type": "block" } }, { "trigger": { "url-filter": "google.com" }, "action": { "type": "ignore-previous-rules" } }]"""let compiledContentRulesList = try await WKContentRuleListStore .default() .compileContentRuleList( forIdentifier: "MyAppList", // Đặt một cái tên định danh cho danh sách này encodedContentRuleList: contentRulesList )webViewConfiguration.userContentController .add(compiledContentRulesList!) // Thêm danh sách đã biên dịch vào WebView```Vậy là xong! Đơn giản mà hiệu quả đúng không?<img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/ios_content_rule_list.png' alt='Cách WKContentRuleList hoạt động trên iOS'>Lời kết: Thế là bạn đã "master" rồi!Giờ thì bạn đã biết cách "can thiệp" và chặn/cho phép các yêu cầu của WebView trên cả Android lẫn iOS rồi đó! Android thì đơn giản và trực diện hơn nhiều, còn iOS thì cần một chút "mánh khóe" với WKContentRuleList. Hy vọng trong tương lai, Apple sẽ cung cấp một cách làm dễ dàng hơn nữa!Cảm ơn bạn đã đọc nhé! Nếu có bất kỳ câu hỏi nào, đừng ngần ngại cho mình biết nha!