All articles

Technical

Web-to-Native Communication in Android TWAs

October 5, 2026 · 8 min read

When developers build hybrid mobile apps using traditional WebViews, they rely on a bridge called addJavascriptInterface to execute native Java or Kotlin methods directly from JavaScript. In a Trusted Web Activity (TWA), this approach is intentionally blocked. Because a TWA executes your web app inside a sandboxed Chrome system process for security and performance reasons, you cannot inject arbitrary Java objects into the web runtime.

Despite this security model, many applications still require reliable communication between the web app context and the underlying native Android shell. Whether you need to pass system-level hardware states to your frontend, coordinate custom push notification tokens, or trigger native SDK actions, you must employ alternative web-standard communication protocols. This guide explores the secure, verified methods for establishing web-to-native communication in a TWA app.

Why Custom JS Interfaces are Blocked in TWAs

In standard WebView implementations, injecting a JavaScript interface creates a significant security risk. If your web app is compromised or loads a third-party script via an injection attack, that malicious script gains direct access to the native Android capabilities exposed through the bridge. It can read local files, access databases, or make privileged device requests.

TWAs enforce a strict separation of concerns. The web context and the native application context are isolated. To share information, both sides must agree on highly structured, explicit message channels. This prevents arbitrary code execution while allowing structured data exchange.

Method 1: The PostMessage API Channel

The most robust, secure, and officially supported method for bi-directional communication between a TWA web page and the native Android wrapper is the Custom Tabs PostMessage API. This mimics the standard web window.postMessage protocol, bringing it to the native Android app context.

To implement this, you must bind to a native service in your Android app shell that handles the message channel connection. Once the connection is validated through your Digital Asset Links, your web app can send messages that are parsed directly by your native Kotlin or Java code.

The Native Android Implementation

Your Android app shell must register a CustomTabsServiceConnection and establish a CustomTabsSession. This session is used to initialize the message channel. You must implement a helper class that listens for messages received from the browser context.

When a message arrives from the web client, it triggers a callback in your native code, containing the message body as a string. Your Android application can then parse this payload (typically formatted as a JSON string) and execute the appropriate native action, such as requesting a system service, interacting with a local database, or raising a native notification.

The Web JavaScript Implementation

On the web client side, the browser exposes the postMessage target on the native side. Once the session is fully established by the Android OS, you can transmit messages securely. It is standard practice to listen for the initialization event and store the target port for future transmissions.

Because this channel depends on validation, it will only work when your Digital Asset Links are fully verified and the application is running inside the signed Android package. If accessed through a standard mobile browser, the communication target will be undefined, allowing your PWA to degrade gracefully to regular web behaviour.

Method 2: Intercepting Custom URL Schemes

Another reliable, unidirectional method for sending commands from the web app to the native wrapper is using custom URL schemes or intent filters. Instead of relying on active message channels, your web app triggers a navigation event to a specific protocol or path that your native app shell is configured to intercept.

For example, you can use a custom scheme like myapp://action?type=share&payload=data. By setting up an Intent Filter in your Android Manifest, your native wrapper can intercept this specific URL pattern before Chrome attempts to handle it externally.

Configuring the Android Manifest

To intercept custom schemes, you define an activity tag inside your AndroidManifest.xml. This tells the Android operating system that your app is the default handler for your custom protocol.

When your web application attempts to redirect the window location to your custom scheme, the Android OS intercepts the intent and passes the target URI to your specified Activity. Your native code then extracts the query parameters from the URI and performs the requested system operations.

Method 3: Query Parameter Bootstrapping

Sometimes you only need unidirectional communication from the native Android app to your web application during the initial launch phase. This is common when you need to pass device-specific information to your web frontend, such as the Android OS version, the app version code, or a native install referrer token.

This is achieved by appending custom query parameters to the TWA launch URL. When your Android shell launches the Trusted Web Activity, it reads the current device state and app configuration, then modifies the launch intent's destination URI before presenting it to the Custom Tab browser.

Example Query Parameter Appends

Parameter NameExample ValueUse Case in Web Application
utm_sourceplaystoreIdentifies that the traffic originated from the installed Android app.
app_version2.1.4Enables conditional rendering of web features based on native shell capabilities.
android_sdk33Adapts web layout or media processing based on the user's Android system level.

On your web application side, you can parse these parameters on initial page load using standard JavaScript URL parsing objects. This allows you to immediately customize the user interface, disable web-based install prompts, or log native-specific analytics events immediately upon startup.

Choosing the Right Communication Method

The choice of communication channel depends heavily on the frequency and direction of your data transfer requirements. The following rules of thumb can help guide your architecture:

  • Use Query Parameters if you only need to send metadata from Android to the Web once during application startup.
  • Use Custom URL Schemes if you need simple, one-way triggers from the Web to the Android app shell, such as opening a native setting screen or calling an SDK.
  • Use the PostMessage API if your application requires active, real-time bi-directional messaging, such as continuous data streaming or interactive query-and-response patterns.

Ready to ship your Android app?

Paste your PWA URL, get a signed APK and a Google Play ready AAB in minutes.

Build my app