JsBridge: Bidirectional Java and JavaScript Communication for Android WebView
android java and javascript bridge, inspired by wechat webview jsbridge
At a glance
- What is it?
- JsBridge is an Android library that connects Java code to JavaScript running in a WebView, supporting calls in both directions, persistent multi-response callbacks, and an optional domain whitelist that restricts which origins can invoke native methods.
- Who is it for?
- JsBridge fits Android projects that embed a WebView and need reliable two-way communication between Java code and JavaScript, without rewriting the WebView from scratch. The BridgeWebView drop-in path covers most cases.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 18 days ago.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What JsBridge Solves in Android WebView Development
Android's WebView provides a built-in addJavascriptInterface() method for exposing Java objects to JavaScript, but it has well-documented security issues in older API levels and an awkward callback model. When JavaScript needs to invoke Java code and receive a response, the standard interface provides no direct mechanism: the developer must manage response routing manually.
JsBridge addresses this with a handler-based messaging system that works in both directions with explicit callbacks. Java code can call a JavaScript handler by name and receive a response through a callback interface. JavaScript code can call a Java handler and receive a response the same way. The callback mechanism is explicit rather than implicit, and the response routing is managed by the library rather than by application code.
The README describes the library as a bridge between Android Java and JavaScript for WebView, inspired by the WeChat WebView JSBridge. The target user is an Android developer embedding a WebView that needs to exchange data between the native layer and the web content it displays, whether that content is a local HTML file or a remote page.
Android's raw evaluateJavascript() method lets Java call into JavaScript but provides no structured way to receive a response. The developer has to invent a calling convention, typically by having JavaScript call back through another evaluateJavascript or addJavascriptInterface invocation with the result. JsBridge formalizes that pattern: every call has a named handler on the receiving side and a callback on the calling side, so the response arrives at a predictable location without any custom routing code in the application. This removes a class of bugs where responses arrive at the wrong callback or in the wrong order when multiple asynchronous calls are in flight simultaneously. The library manages a callback registry keyed by call identifier, and each callback is matched to its call by that identifier rather than by sequencing.
Installing JsBridge via JitPack
JsBridge is distributed through JitPack rather than Maven Central. The installation requires two Gradle changes. First, add the JitPack repository to the project-level settings.gradle or build.gradle:
repositories {
maven { url "https://jitpack.io" }
}Then add the dependency at the module level:
dependencies {
implementation 'com.github.happydog-intj:JsBridge:v2.1.0'
}The library is in the library/ directory of the repository. The example/ directory contains a working Android application that demonstrates both the BridgeWebView and BridgeHelper integration paths.
BridgeWebView: The Drop-In Integration Path
For projects that can replace their standard WebView with a custom subclass, BridgeWebView is the primary integration point. Add it to the layout:
<com.github.lzyzsd.jsbridge.BridgeWebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent" />In the Activity, initialize it and register the JavaScript interface:
BridgeWebView webView = findViewById(R.id.webView);
webView.setGson(new Gson());
webView.addJavascriptInterface(
new MainJavascriptInterface(
webView.getCallbacks(),
webView.getPersistentCallbacks(),
webView),
"WebViewJavascriptBridge");
webView.loadUrl("file:///android_asset/demo.html");The bridge JavaScript is injected automatically on page load. The JavaScript side does not need to include a separate script file. The WebViewJavascriptBridge object becomes available globally in the page context once injection completes.
The BridgeWebView subclass configures the underlying WebView with JavaScript enabled and a WebViewClient implementation that injects the bridge JavaScript on every page load. The injection happens in onPageStarted, so the bridge is available before the page's own JavaScript runs, and the WebViewJavascriptBridge global is present by the time any inline scripts execute. The setGson call on line four of the initialization block supplies a Gson instance for Java-side serialization. Any Java object passed as data to callHandler is serialized to JSON using that Gson instance before being handed to the JavaScript side. This means the data parameter in JavaScript always arrives as a JSON string, not a raw Java object, and the JavaScript side is responsible for parsing it with JSON.parse() if the data is structured. The README's examples pass a user object from Java, which Gson converts to a JSON string before the bridge sends it.
Calling Between Java and JavaScript in Both Directions
Calls from Java to JavaScript work by registering a named handler on the JavaScript side, then calling it by name from Java. On the JavaScript side:
WebViewJavascriptBridge.registerHandler("functionInJs", function(data, responseCallback) {
document.getElementById("show").innerHTML = "data from Java: = " + data;
responseCallback("Javascript Says Right back aka!");
});From Java, call the registered handler:
webView.callHandler("functionInJs", new Gson().toJson(user), new OnBridgeCallback() {
@Override
public void onCallBack(String data) {
Log.d(TAG, "response from JS: " + data);
}
});Calls from JavaScript to Java work in the opposite direction. A class implementing BridgeWebView.BaseJavascriptInterface handles incoming calls:
public class MainJavascriptInterface extends BridgeWebView.BaseJavascriptInterface {
@Override
public String send(String data) {
return "default response";
}
}From JavaScript, invoking the Java handler:
WebViewJavascriptBridge.callHandler(
'submitFromWeb',
{'param': 'value'},
function(responseData) {
document.getElementById("show").innerHTML = "response: " + responseData;
}
);Data is serialized as strings in both directions. The README examples use Gson for Java-side serialization and plain JSON in JavaScript.
Persistent Callbacks for Multi-Response Scenarios
By default, a callback is removed from the registry after its first invocation. This is the standard request-response pattern. For scenarios where JavaScript needs to receive multiple responses from a single call, such as real-time updates, event streams, or progress notifications, the library provides persistent callbacks:
webView.callHandlerPersistent("functionInJs", data, new OnBridgeCallback() {
@Override
public void onCallBack(String data) {
Log.d(TAG, "called again: " + data); // can be called multiple times
}
});The persistent callback remains in the registry until explicitly removed, so the JavaScript side can call the response callback multiple times and each call will reach the Java handler.
The distinction matters in practice: a file upload progress bar, a streaming text display, or a continuous sensor update all require the JavaScript side to push multiple data points back to Java without opening a new call for each one. Standard callbacks would require either one call per update or a polling model.
Domain Whitelist Security and the BridgeHelper Path
The domain whitelist is a security feature that restricts which origins can invoke @JavascriptInterface methods through the bridge. By default, the whitelist is empty, meaning all origins are allowed. This preserves backward compatibility but leaves the bridge open to any page loaded in the WebView.
To restrict access:
webView.addAllowedHost("example.com");
webView.addAllowedHost("*.example.com"); // wildcard for subdomainsOr use BridgeConfig for full control:
BridgeConfig config = new BridgeConfig();
config.addAllowedHost("example.com");
webView.setBridgeConfig(config);For projects using a custom WebView subclass that cannot extend BridgeWebView, the BridgeHelper class provides the same functionality without requiring the class hierarchy change. The custom WebView implements the IWebView interface, and BridgeHelper is held as a member:
private BridgeHelper bridgeHelper = new BridgeHelper(this);The whitelist applies to BridgeHelper through the same API:
webView.bridgeHelper.addAllowedHost("example.com");For projects that load content from URLs outside their own domain, setting the whitelist is the only mechanism the library provides to prevent third-party pages from calling native methods.
JavaScript Bridge Readiness and Comparison with addJavascriptInterface
The bridge JavaScript is injected automatically on page load, but the injection is asynchronous. The README documents two patterns for checking readiness before using the bridge in JavaScript:
function setupWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
return callback(WebViewJavascriptBridge);
}
if (window.WVJBCallbacks) {
return window.WVJBCallbacks.push(callback);
}
window.WVJBCallbacks = [callback];
}Alternatively, listen for the DOM event:
document.addEventListener('WebViewJavascriptBridgeReady', function() {
// bridge is now ready
}, false);Compared to Android's built-in addJavascriptInterface(), JsBridge adds explicit callback management, named handler registration on both sides, persistent callbacks, and the whitelist security model. The trade-off is that both the Java layer and the JavaScript page must follow the bridge pattern: pages that do not register handlers cannot receive calls from Java, and Java code must use the bridge API rather than evaluateJavascript() directly. For a new project, this is straightforward. For a project with existing direct evaluateJavascript() calls, adopting JsBridge requires reworking those call sites.
Repository Structure and What to Expect from the Example App
The repository is organized with the library in the library/ directory and a complete working example application in the example/ directory. The example app demonstrates all the integration patterns documented in the README: BridgeWebView initialization, Java-to-JavaScript calls, JavaScript-to-Java calls, persistent callbacks, and the domain whitelist.
The top-level build.gradle and settings.gradle configure the multi-module Android project. The library/build.gradle builds the JsBridge library module itself. Developers who want to inspect the bridge source code rather than consume it through JitPack can clone the repository and import the project into Android Studio directly.
The README includes a Chinese documentation section in addition to the English section, covering the same API with the same code examples. Both sections are part of the same README file, indicated by the [English] and [中文文档] anchor navigation at the top. The architecture diagram at the top of the README (JsBridgeWork.png) illustrates the two-way message flow between the JavaScript and Java layers.
The library README does not document the minimum Android API level required or a maximum tested version. The JitPack dependency uses version v2.1.0 as shown in the install example; the dependency version string com.github.happydog-intj:JsBridge:v2.1.0 is the current reference point from the README. There are no GitHub releases published in the repository; JitPack resolves the library version from the v2.1.0 git tag.
For projects that load content from a Content Security Policy-restricted domain, the domain whitelist feature interacts with the WebView's own origin model. The whitelist in BridgeConfig uses host strings and supports wildcard subdomain patterns (*.example.com), but the README does not document interaction with Android's WebSettings.setAllowFileAccessFromFileURLs() or WebSettings.setAllowUniversalAccessFromFileURLs() settings. Projects that load local HTML files from assets and also load remote pages should test the whitelist behavior against their specific URL patterns before relying on it as a security boundary.
Editorial conclusion
JsBridge fits Android projects that embed a WebView and need reliable two-way communication between Java code and JavaScript, without rewriting the WebView from scratch. The BridgeWebView drop-in path covers most cases. For teams using a custom WebView subclass, the BridgeHelper approach integrates without requiring a class hierarchy change. The domain whitelist is a meaningful security control that is off by default: any project loading untrusted URLs into the WebView should set allowed hosts explicitly. The repository has no license file listed and no GitHub releases; versioning is managed through JitPack against tags like v2.1.0. The last push was on 2026-09-12.
Frequently asked questions
What is JsBridge for Android?
JsBridge is an Android library that provides bidirectional communication between Java code and JavaScript running inside a WebView. It replaces direct addJavascriptInterface() usage with a named handler system that supports callbacks in both directions.
What is a JsBridge method and how does it work?
A JsBridge method is a named handler registered on either the Java or the JavaScript side. Java registers @JavascriptInterface methods; JavaScript registers handlers with WebViewJavascriptBridge.registerHandler(). Callers on either side invoke a handler by name and pass a callback to receive the response.
How do I handle the JsBridge method not found error?
This error occurs when one side calls a handler name that has not been registered on the other side. Verify that the JavaScript or Java handler is registered before any call is made to it. For JavaScript handlers, use the setupWebViewJavascriptBridge pattern documented in the README to ensure the bridge is ready before registering handlers.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/happydog-intj-jsbridge)