Mastering WebView & JSBridge: Seamless Native‑Web Communication on Android & iOS
This article explains the fundamentals of WebView as a native container for H5, introduces the JSBridge concept for two‑way JavaScript‑Native messaging, and provides detailed implementation patterns and code samples for Android (JavascriptInterface, URL‑Scheme, WebChromeClient) and iOS (WKWebView, user scripts, message handlers).
WebView Overview
WebView is a component that displays web pages inside a native app, built on the WebKit rendering engine and providing basic browser capabilities such as navigation, zoom, and history.
WebView can be thought of as an iframe inside a native app; the native side and the WebView share a common Window and can communicate through a bridge.
JSBridge Concept
JSBridge supplies an interface for JavaScript to invoke native functionality, enabling two‑way communication between the web page and the native layer.
JS → Native: call functions, notify native of page state.
Native → JS: return results, push messages, notify JS of native state.
Because JavaScript runs in an isolated context (WebKit, JSCore, etc.), the interaction can be modeled as Remote Procedure Calls (RPC).
Android WebView Implementation
Since Android 4.4 the WebView core switched from WebKit to Chromium, improving performance and HTML5 support.
Three main ways to enable JS‑Native communication:
JavascriptInterface : expose a Java object to JavaScript.
WebViewClient.shouldOverrideUrlLoading() : intercept custom URL schemes.
WebChromeClient.onXXX() : handle alerts, confirms, prompts, and console messages.
<code>public class WebAppInterface {</code><code> @JavascriptInterface</code><code> public void showToast(String toast) {</code><code> Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();</code><code> }</code><code>}</code> <code>WebView webView = (WebView) findViewById(R.id.webview);</code><code>webView.addJavascriptInterface(new WebAppInterface(this), "Android");</code> <code>function showAndroidToast(toast) {</code><code> Android.showToast(toast);</code><code>}</code> <code>public class CustomWebViewClient extends WebViewClient {</code><code> @Override</code><code> public boolean shouldOverrideUrlLoading(WebView view, String url) {</code><code> if (isJsBridgeUrl(url)) {</code><code> // handle JSBridge URL</code><code> return true;</code><code> }</code><code> return super.shouldOverrideUrlLoading(view, url);</code><code> }</code><code>}</code> <code>public class CustomWebChromeClient extends WebChromeClient {</code><code> @Override</code><code> public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {</code><code> // process JS prompt</code><code> result.confirm();</code><code> return true;</code><code> }</code><code>}</code>For Android KitKat (4.4) and later, Java can also execute JavaScript via
evaluateJavascript:
<code>webView.evaluateJavascript(javaScriptString, new ValueCallback<String>() {</code><code> @Override</code><code> public void onReceiveValue(String value) {</code><code> // handle result</code><code> }</code><code>});</code>iOS WebView Implementation
Before iOS 8,
UIWebViewwas used and suffered from slow loading, memory leaks, and high memory usage. Since iOS 8,
WKWebViewreplaces UIWebView, offering a modern WebKit engine, 60 fps rendering, and a unified API.
JavaScript ↔ Swift Communication
Inject user scripts with
WKUserScriptto run JavaScript before or after page load.
<code>let source = "document.body.style.background = \"#777\""</code><code>let userScript = WKUserScript(source: source, injectionTime: .atDocumentEnd, forMainFrameOnly: true)</code><code>let userContentController = WKUserContentController()</code><code>userContentController.addUserScript(userScript)</code><code>let configuration = WKWebViewConfiguration()</code><code>configuration.userContentController = userContentController</code><code>self.webView = WKWebView(frame: self.view.bounds, configuration: configuration)</code>Message handlers allow JavaScript to send messages to native code:
<code>window.webkit.messageHandlers.notification.postMessage({body: 'send to Native'});</code> <code>class NotificationScriptMessageHandler: NSObject, WKScriptMessageHandler {</code><code> func userContentController(_ userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {</code><code> print(message.body)</code><code> }</code><code>}</code><code>let userContentController = WKUserContentController()</code><code>let handler = NotificationScriptMessageHandler()</code><code>userContentController.addScriptMessageHandler(handler, name: "notification")</code>Summary
The core of native‑web communication is the JSBridge, which can be implemented via injected APIs (JavascriptInterface on Android, WKUserScript on iOS) for JavaScript‑to‑Native calls, and by executing JavaScript strings for Native‑to‑JavaScript calls. Similar patterns apply to frameworks like React Native or WeChat Mini‑Programs.
Tencent IMWeb Frontend Team
IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.