Android/iOS原生App中检测特定URL后关闭WebView的实现方案
Hey there! I totally get the frustration—window.close() rarely works as expected in native WebViews because they don’t follow the same rules as desktop browsers. Let’s walk through reliable solutions for both Android and iOS, focusing on two common approaches: URL interception and direct JavaScript-native communication.
Option 1: Intercept the Target URL in WebViewClient
You can set up a custom WebViewClient to watch for your specific URL, then trigger the WebView (or its containing Activity/Fragment) to close when detected.
// Inside your Activity or Fragment val webView = findViewById<WebView>(R.id.your_webview_id) webView.settings.javaScriptEnabled = true webView.webViewClient = object : WebViewClient() { override fun shouldOverrideUrlLoading( view: WebView?, request: WebResourceRequest? ): Boolean { request?.url?.toString()?.let { url -> // Replace this with your target URL or custom scheme if (url == "https://your-domain.com/close-webview" || url.startsWith("myapp://close")) { // Close the hosting Activity finish() // If using a Fragment, use requireActivity().finish() or popBackStack() instead return true // Tell WebView we've handled this navigation } } return super.shouldOverrideUrlLoading(view, request) } }
Option 2: JavaScript-Native Bridge (More Flexible)
Create a bridge so your web content can directly call a native method to close the WebView. This is cleaner than URL interception for explicit actions like this.
First, define a native interface class:
class WebViewBridge(private val context: Context) { // Annotate with @JavascriptInterface to expose to JS @JavascriptInterface fun closeWebView() { (context as Activity).runOnUiThread { context.finish() } } }
Then attach it to your WebView:
webView.addJavascriptInterface(WebViewBridge(this), "NativeApp")
Now in your web content, call the native method directly:
// Trigger this when you want to close the WebView window.NativeApp.closeWebView();
We’ll use WKWebView (the modern replacement for UIWebView) here—it’s more performant and has better JS-native communication support.
Option 1: Intercept Custom URL Scheme
Set up a WKNavigationDelegate to check for your target URL and close the view controller when matched.
import WebKit class WebViewVC: UIViewController, WKNavigationDelegate { private var webView: WKWebView! override func viewDidLoad() { super.viewDidLoad() let config = WKWebViewConfiguration() webView = WKWebView(frame: view.bounds, configuration: config) webView.navigationDelegate = self view.addSubview(webView) // Load your initial web URL if let url = URL(string: "https://your-web-content.com") { webView.load(URLRequest(url: url)) } } func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { guard let url = navigationAction.request.url else { decisionHandler(.allow) return } // Check for your target URL or custom scheme if url.scheme == "myapp" && url.host == "close-webview" { dismiss(animated: true) decisionHandler(.cancel) // Cancel the navigation return } decisionHandler(.allow) } }
Option 2: WKScriptMessageHandler (JS-Native Bridge)
This lets your web content send a message directly to native code to trigger the close action.
import WebKit class WebViewVC: UIViewController, WKScriptMessageHandler { private var webView: WKWebView! override func viewDidLoad() { super.viewDidLoad() let config = WKWebViewConfiguration() // Add a message handler with a unique name config.userContentController.add(self, name: "closeWebView") webView = WKWebView(frame: view.bounds, configuration: config) view.addSubview(webView) // Load your web content if let url = URL(string: "https://your-web-content.com") { webView.load(URLRequest(url: url)) } } // Handle messages from JS func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { if message.name == "closeWebView" { dismiss(animated: true) } } // Clean up to avoid memory leaks deinit { webView.configuration.userContentController.removeScriptMessageHandler(forName: "closeWebView") } }
In your web content, send the message like this:
// Trigger close window.webkit.messageHandlers.closeWebView.postMessage(null);
Quick Notes
- For both platforms, the JS-native bridge approach is usually preferred—it’s more explicit and avoids conflicts with normal web navigation.
- On Android, make sure you’re not using Chrome Custom Tabs (they don’t support
addJavascriptInterfaceor URL interception for closing). - On iOS, avoid UIWebView entirely—it’s deprecated and lacks modern features.
内容的提问来源于stack exchange,提问作者Bhavesh Chauhan

