Mastering JsBridge: Connecting JavaScript and Java in Android Apps
This article explains how Android hybrid apps enable JavaScript‑Java communication, compares four JS‑to‑Java methods, shows the single Java‑to‑JS approach, and provides a detailed walkthrough of the open‑source JsBridge library with code samples and workflow diagrams.
1. JavaScript‑to‑Java and Java‑to‑JavaScript mechanisms
Android provides four common ways for JavaScript running in a WebView to invoke native Java code: JavascriptInterface – official API; methods must be annotated with @JavascriptInterface and are available on Android 4.2 (API 17) and later. WebViewClient.shouldOverrideUrlLoading() – intercept specially‑formatted URLs and route them to native logic. WebChromeClient.onConsoleMessage() – captures console.log() output from JavaScript and forwards it to Java. WebChromeClient.onJsPrompt() – handles calls to window.prompt(); widely used in JsBridge implementations.
Typical JavascriptInterface implementation:
public class JavascriptInterface {
@JavascriptInterface
public void showToast(String toast) {
Toast.makeText(MainActivity.this, toast, Toast.LENGTH_SHORT).show();
}
}Register the interface with the WebView:
webView.addJavascriptInterface(new JavascriptInterface(), "javascriptInterface");JavaScript can then call the native method:
function showToast(toast) {
javascriptInterface.showToast(toast);
}Java can invoke JavaScript by loading a javascript: URL, e.g.:
webView.loadUrl(String.format(
"javascript:WebViewJavascriptBridge._handleMessageFromNative(%s)", data));2. JsBridge library
JsBridge is an open‑source Android library that unifies the four JS‑to‑Java techniques and provides a bidirectional message‑passing protocol. Repository: https://github.com/lzyzsd/JsBridge
2.1 Registering handlers and calling from Java
Java registers a handler that JavaScript can invoke:
webView.registerHandler("submitFromWeb", new BridgeHandler() {
@Override
public void handler(String data, CallBackFunction function) {
Log.i(TAG, "handler = submitFromWeb, data = " + data);
function.onCallBack("response data from Java");
}
});Java can also call a JavaScript handler:
webView.callHandler("functionInJs",
new Gson().toJson(user),
new CallBackFunction() {
@Override
public void onCallBack(String data) {
// process response from JavaScript
}
});2.2 Message creation and queueing in Java
When callHandler is executed, JsBridge builds a Message object, assigns a unique callbackId (if a response is expected), stores the callback in responseCallbacks, and queues the message:
private void doSend(String handlerName, String data,
CallBackFunction responseCallback) {
Message m = new Message();
if (!TextUtils.isEmpty(data)) {
m.setData(data);
}
if (responseCallback != null) {
String callbackStr = String.format(
BridgeUtil.CALLBACK_ID_FORMAT,
++uniqueId + BridgeUtil.UNDERLINE_STR + SystemClock.currentThreadTimeMillis());
responseCallbacks.put(callbackStr, responseCallback);
m.setCallbackId(callbackStr);
}
if (!TextUtils.isEmpty(handlerName)) {
m.setHandlerName(handlerName);
}
queueMessage(m);
}The queued message is eventually sent to JavaScript via:
loadUrl(String.format(
BridgeUtil.JS_HANDLE_MESSAGE_FROM_JAVA, messageJson));2.3 Injecting the bridge JavaScript
After the HTML page finishes loading, BridgeWebViewClient.onPageFinished injects WebViewJavascriptBridge.js from the app’s assets into the WebView.
2.4 JavaScript side processing
The injected script defines _handleMessageFromNative, parses the JSON message, creates a response callback when callbackId is present, looks up the appropriate handler in messageHandlers, and executes it:
function _dispatchMessageFromNative(messageJSON) {
setTimeout(function() {
var message = JSON.parse(messageJSON);
var responseCallback;
if (message.responseId) {
// handle response from Java
} else {
if (message.callbackId) {
var callbackResponseId = message.callbackId;
responseCallback = function(responseData) {
_doSend({responseId: callbackResponseId,
responseData: responseData});
};
}
var handler = WebViewJavascriptBridge._messageHandler;
if (message.handlerName) {
handler = messageHandlers[message.handlerName];
}
try {
handler(message.data, responseCallback);
} catch (e) {
console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, e);
}
}
});
}2.5 Returning results to Java
The JavaScript responseCallback calls _doSend, which pushes a response message onto the queue and changes a hidden iframe’s src. This triggers WebViewClient.shouldOverrideUrlLoading on the Java side, which calls webView.flushMessageQueue(). The method loads the queued messages back into Java, deserializes them, and invokes the stored CallBackFunction objects.
3. Summary
JsBridge abstracts the four native‑to‑JS invocation methods and the single JS‑to‑native method into a consistent, bidirectional messaging system. Understanding the flow—handler registration, message construction, queueing, JavaScript injection, and callback handling—enables reliable hybrid Android development.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Tencent Music Tech Team
Public account of Tencent Music's development team, focusing on technology sharing and communication.
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.
