Mobile Development 14 min read

An Introduction to JSBridge: Origin, Dual‑Communication Principles, and Usage

This article explains the origin of JSBridge, compares H5 and native development, details the two‑way communication mechanisms—including URL Scheme interception, prompt rewriting, and API injection—and provides practical usage guidelines and code examples for integrating JSBridge in hybrid mobile apps.

政采云技术
政采云技术
政采云技术
An Introduction to JSBridge: Origin, Dual‑Communication Principles, and Usage

JSBridge is a JavaScript‑based bridge that connects Web (H5) pages with native code in mobile applications, enabling two‑way communication so that JavaScript can call native functions (e.g., opening the camera, accessing the album, fingerprint payment) and native code can invoke JavaScript.

Origin of JSBridge

With the rapid proliferation of mobile devices, developers often need to combine native and H5 approaches in hybrid applications. Early solutions like Cordova provided APIs for JavaScript to call native code, but JSBridge became widely adopted in China as mobile internet grew.

H5 vs. Native Comparison

Aspect

H5

Native

Stability

Relies on system browser kernel, less stable

Uses native kernel, more stable

Flexibility

Fast iteration, easy release

Slower iteration, app‑store review required

Network Impact

Higher

Lower

Smoothness

Sometimes slow, feels laggy

Fast loading, smoother experience

User Experience

Limited by browser capabilities

Rich native APIs, better UX

Portability

Cross‑platform (PC, iOS, Android)

Separate codebases for iOS and Android

Dual‑Communication Principles

JS Calls Native

Common methods include intercepting URL Scheme , rewriting prompt , and injecting APIs.

Intercepting URL Scheme

Both Android and iOS can capture a custom URL scheme and decide whether to execute native logic.

On Android, WebView provides shouldOverrideUrlLoading to intercept the request:

public class CustomWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        // Scene 1: intercept request, handle scheme
        if (url.equals("xxx")) {
            // handle
            view.loadUrl("javascript:setAllContent(" + json + ");");
            return true;
        }
        return super.shouldOverrideUrlLoading(url);
    }
}

On iOS, WKWebView can process the intercepted scheme:

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    if ([navigationAction.request.URL.absoluteString hasPrefix:@"xxx"]) {
        [[UIApplication sharedApplication] openURL:navigationAction.request.URL];
    }
    decisionHandler(WKNavigationActionPolicyAllow);
}

This method is flexible and avoids security issues, but URL length must be controlled.

Rewriting Prompt and Other Native JS Methods

Before Android 4.2, addJavascriptInterface was used, but due to security concerns developers now intercept alert , confirm , prompt , and console.log via WebView callbacks.

public boolean onJsPrompt(WebView view, String origin, String message, String defaultValue, final JsPromptResult result) {
    String handledRet = parentEngine.bridge.promptOnJsPrompt(origin, message, defaultValue);
    // ...
    return true;
}

On iOS, the three WKUIDelegate methods must be implemented to handle these dialogs.

-(void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:[UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        completionHandler();
    }]];
    [self presentViewController:alertController animated:YES completion:nil];
}

Injecting API

By injecting an object into the WebView’s JavaScript context, JS can directly call native methods.

gpcWebView.addJavascriptInterface(new JavaScriptInterface(), "nativeApiBridge");
public class JavaScriptInterface {
    Context mContext;
    JavaScriptInterface(Context c) { mContext = c; }
    public void share(String webMessage) { /* Native logic */ }
}

JS usage:

window.NativeApi.share(xxx);

iOS provides window.webkit.messageHandlers for similar injection.

window.webkit.messageHandlers.share.postMessage(xxx);

Native Calls JS

Native can execute JavaScript by loading a URL or using evaluation APIs.

Android (pre‑4.4) uses loadUrl("javascript:" + js) ; Android 4.4+ prefers evaluateJavascript which returns a result without refreshing the WebView.

webView.loadUrl("javascript:" + javaScriptString);
webView.evaluateJavascript(javaScriptString, new ValueCallback
() {
    @Override
    public void onReceiveValue(String value) {
        // handle result
    }
});

iOS WKWebView uses evaluateJavaScript:completionHandler: :

func evaluateJavaScript(_ javaScriptString: String, completionHandler: ((Any?, Error?) -> Void)? = nil) {
    // ...
}

Using JSBridge

Two main ways to reference the bridge:

H5‑side local import (npm package) – simple but tightly coupled to a specific implementation.

Native‑side injection – preferred in our team; keeps API consistent with native code but requires runtime checks for bridge availability.

Typical H5‑to‑Native call pattern:

params = {
  api_version: "xxx",
  title: "xxx",
  filename: "xxx",
  image: "xxx",
  url: "xxx",
  success: function(res) { /* success */ },
  fail: function(err) {
    if (err.code == '-2') {
      // API version not supported
    } else {
      const msg = err.msg;
      Toast.fail(msg);
    }
  }
};
window.NativeApi.share(params);

A helper function checks whether the app environment and bridge exist before invoking native methods:

reqNativeBridge(vm, fn) {
  if (!isApp()) {
    vm.$dialog.alert({ message: "此功能需要访问 APP 才能使用" });
  } else if (!window.NativeApi) {
    vm.$dialog.alert({ message: "请更新到最新 APP 使用该功能" });
  } else {
    fn && fn(err => {
      vm.$dialog.alert({ message: "请更新到最新 APP 使用该功能" });
    });
  }
}

Conclusion

The article provides a concise overview of JSBridge’s principles, common implementation techniques, and practical usage patterns, offering a useful reference for developers new to hybrid mobile development.

mobileNativeJavaScripthybrid-developmentWebViewJSBridge
政采云技术
Written by

政采云技术

ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.