In-depth Profiling of JSBridge

Image for post
Image for post


Developers who have been involved in hybrid development are familiar with frameworks such as Ionic and PhoneGap. These frameworks cover a web-based app in a Native layer and then call the local library through the JSBridge technology.

Android Environment

Calling JS in Native

Calling JS in Native is relatively simple: you just need to observe the rule of “javascript: method name ('parameter, needed to be converted to string')".

// mWebView = new WebView(this);            
mWebView.loadUrl("javascript: method name ('parameter, needed to be converted to string')");
//Run in UI thread
runOnUiThread(new Runnable() {
public void run() {
mWebView.loadUrl("javascript: method name ('parameter, needed to be converted to string')");
Toast.makeText(Activity name.this, "call method...", Toast.LENGTH_SHORT).show();
mWebView.evaluateJavascript("javascript: method name ('parameter, needed to be converted to string')", new ValueCallback() {
public void onReceiveValue(String value) {
//Here the value refers to the returned value of the corresponding JS method
  • For Android 4.4 and newer versions, the JS methods are called asynchronously through evaluateJavascript and the returned value is available in onReceiveValue.
  • This method is not suitable for transmission of large amounts of data (the interface approach is recommended for a large amount of data).
  • mWebView.loadUrl(“javascript: The mWebView.loadUrl (“javascript:method name (‘parameter, needed to be converted to string’”)”) function needs to be run in the UI thread because mWebView is a UI control.

Calling Native in JS

The call of Native in JS requires the @JavascriptInterface annotation to the WebView. There is a loophole, which will be explained later. To make JS native, you need to set the following attributes for WebView:

WebSettings webSettings = mWebView.getSettings();  
//Android container allows JS scripts
//Android container sets the bridge object
mWebView.addJavascriptInterface(getJSBridge(), "JSBridge");
private Object getJSBridge(){  
Object insertObj = new Object(){
public String foo(){
return "foo";
public String foo2(final String param){
return "foo2:" + param;
return insertObj;
//Call method 1; //Returned: 'foo'
//Call method 2
window.JSBridge.foo2('test');//Returned: 'foo2:test'
  • Before API17, addJavascriptInterface has a potential security risk. Hackers can get the Native-registered JS object by decompiling and obtaining sensitive information, and then launching attacks by reflecting Java's built-in static classes on the page.
  • JS calls Native-exposed API and gets the corresponding returned value.

iOS Environment

Calling JS in Native

The method to call JS in Native is relatively simple. Native calls the function that HTML binds to the window through stringByEvaluatingJavaScriptFromString. Note the OC and Swift writing styles.

webview.stringByEvaluatingJavaScriptFromString("method name (parameter)")
[webView stringByEvaluatingJavaScriptFromString:@"method name (parameter);"];
  • This method is not suitable for transmission of large amounts of data (the interface approach is recommended for a large amount of data).

Calling Native in JS

In Native, the API can be bound to JSContext through the introduction of the official JavaScriptCore library (iOS7 and above) (and then JS can be called in HTML through ***).

#import <JavaScriptCore/JavaScriptCore.h>
-(void)webViewDidFinishLoad:(UIWebView *)webView{
[self hideProgress];
[self setJSInterface];
-(void)setJSInterface{ JSContext *context =[_wv valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; // API method registered with a name of "foo"
context[@"foo"] = ^() {
//Get the parameter
NSArray *args = [JSContext currentArguments];
NSString *title = [NSString stringWithFormat:@"%@",[args objectAtIndex:0]];
//Do some logic of your own
//A value is returned: 'foo:'+title
return [NSString stringWithFormat:@"foo:%@", title];
  • JS can call the exposed API and get the corresponding returned value.
  • Native iOS cannot be called by JS, but APIs can be made open to JS calls by introducing the official third-party “JavaScriptCore”.

What is JSBridge?

As its name implies, JSBridge serves as a bridge between JS and Native. In fact, JSBridge, also known as the Hybrid app technology, is a communication method between JS and Native. In JSBridge, Native calls JS only through a fixed bridge object, and vice versa.

Image for post
Image for post

JSBridge Implementation Process

The process of JSBridge implementation can be summarized as follows. An H5 page triggers a URL in some way and Native captures the URL for analysis. Native then performs the processing and calls the H5 JSBridge object for transfer and callback.

  • JS is unable to call Native in versions lower than iOS 7.
  • The URL scheme interaction is a set of existing mature solutions that are perfectly compatible with various versions and with the technology of older versions.

URL Scheme

URL scheme is a link, like the URL, designed to facilitate direct mutual calls between apps. You can open the system application for a system URL scheme. Otherwise, you can try to find whether an app has registered such a scheme and open that corresponding app.
Note: A scheme will be valid only after native app registration is completed.

JSBridge: Technical Implementation

To implement JSBridge, we need to analyze the following steps:

  • Step 2: How JS calls Native
  • Step 3: How Native knows that the API is called
  • Step 4: URL-parameter and callback format
  • Step 5: How Native calls JS
  • Step 6: Registration and format of the API method in H5
Image for post
Image for post

Designing Global Bridge Objects for Interaction Between Native and JS

We stipulate that the communication between JS and Native must be implemented through an H5 global object — JSBridge. The object has the following characteristics:

var JSBridge = window.JSBridge || (window.JSBridge = {});
  • callHandler (String, JSON, Function) H5 call. It calls the Native open API, after which the URL scheme is triggered locally. During the call, the callback ID is stored in the local variable responseCallbacks.
  • _handleMessageFromNative (JSON) Native call. Native calls the method registered on the H5 page, or notifies the H5 page of the execution of the callback method.
Image for post
Image for post

Calling Native in JS

After we define the global bridge object, we can use its callHandler method to call the Native API.

//The URL scheme format
//Basically the useful information is the callbackId, handlerName and data at the end
//Native will analyze the scheme after it captures it
var uri = CUSTOM_PROTOCOL_SCHEME://API_Name:callbackId/handlerName?data
//Process of creating the hidden iframe
var messagingIframe = document.createElement('iframe'); = 'none';
//Trigger the scheme
messagingIframe.src = uri;

Native Notifying the API to be Called

In our previous step, we successfully triggered the scheme on the H5 page.
Our next step is to explore how Native captures the scheme triggering event.
Android and iOS have their respective handling approaches.


In Android (in WebViewClient), the shouldoverrideurlloading helps to capture the URL scheme triggering event.

public boolean shouldOverrideUrlLoading(WebView view, String url){
//If false is returned, WebView handles the link URL. If true is returned, WebView executes the URL following the procedures
return true;


iOS, UIWebView has a unique feature: all the network requests initiated in the UIWebView can be notified to the Native layer through the delegate function. In this way, we can capture the URL scheme triggering event in WebView (the principle is to use shouldStartLoadWithRequest).

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSURL *url = [request URL];
NSString *requestString = [[request URL] absoluteString];
//Get the URL scheme for self-processing

Analyzing URL-parameter and Callback Format

In previous steps, Native has received a JS call method. In the next step, Native should parse the data according to the defined data formats. Native can extract the callback parameter ID, API name, and parameters following this format after receiving the URL, and then follow the steps below.

  1. Convert the extracted parameters according to the defined parameters.
  2. Native executes the corresponding API function method locally.
  3. After function execution, find the corresponding callback function ID of this API call, and then assemble the information with the parameter information to be passed into a JSON format parameter.
  4. Notify the H5 page for callback via JSBridge.

Calling JS in Native

In this step, Native calls H5 JS methods through JSBridge or notify H5 for callback. The messageJSON data format in it has two different types.

  • data JSON type: the data to be passed. Its format is fixed to be JSON (because we fix the format of the first parameter received by methods registered in H5 to JSON, and the second to a callback function)
  • callbackId String type: the callback function ID generated by Native. After H5 execution, the URL scheme is used to notify Native about the successful execution of the API and to pass the parameter.

Registration and Format of the API Method in H5

Previously we mentioned that Native takes the initiative to call the API methods registered in H5.
Let us now study, how we can register API methods in H5 for the Native to call.

alert('Test data received by the function:'+JSON.stringify(data));
callback&&callback('Test the postback data...');

Improving the JSBridge Scheme

The diagram below shows a JSBridge object.

Image for post
Image for post
Image for post
Image for post

JSBridge in iOS and Android

In an actual development, how can we develop a unified scheme for different situations in both Android and iOS?

Image for post
Image for post
  • JS calls of Native are no longer through triggering the URL scheme, but through the built-in interaction. Specifically, in Android, Native opens a unified API for JS to call through addJavascriptInterface. Then the URL scheme triggering step is changed to call of the API while the other steps remain the same.


Javascript Bridge is a unified messaging system that enables easy building of cross-language services that allow you to share data and real-time updates among your servers and clients. This article explores in detail the profiling of JSBridge and its implementation process in both iOS and Android respectively.

Written by

Follow me to keep abreast with the latest technology news, industry insights, and developer trends.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store