Tutorial

Configuring Android Network Security for Local TWA Testing

November 14, 2026 · 7 min read

When developing a Progressive Web App (PWA) with the intention of converting it into an Android app via a Trusted Web Activity (TWA), testing on real devices or emulators early in the cycle is critical. However, local development environments typically run over unencrypted HTTP protocol endpoints (such as http://localhost:3000 or http://192.168.1.100). Android enforces strict security policies by default, blocking unencrypted traffic and requiring validated Digital Asset Links, which can completely halt your development process with security errors.

The Cleartext Traffic Restriction in Modern Android

Since the release of Android 9 (API level 28), cleartext (unencrypted HTTP) traffic is disabled by default for all application packages. If your TWA attempts to load an HTTP start URL during development, the system browser engine will immediately block the request and display a net::ERR_CLEARTEXT_NOT_PERMITTED error. To bypass this restriction safely during the development and testing phase, you must configure a custom Network Security Configuration file in your Android project.

Step 1: Creating a Network Security Config File

To permit cleartext HTTP traffic specifically for your local development domains, you must define an XML security resource. This tells the Android operating system to make an exception for your specified hostnames while maintaining strict HTTPS enforcement for production domains.

Create a new XML file named network_security_config.xml within the res/xml directory of your Android project structure. If the xml directory does not exist, create it inside res first.

<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">localhost</domain> <domain includeSubdomains="true">10.0.2.2</domain> <domain includeSubdomains="true">192.168.1.100</domain> </domain-config> </network-security-config>

In this file, 10.0.2.2 is a special IP address that allows an Android emulator to reference the localhost of your development machine. The 192.168.1.100 domain is an example of a local Wi-Fi IP address, which you should replace with your development machine's actual local IP address if you are testing on a physical Android device connected to the same network.

Step 2: Referencing the Config in the App Manifest

Once your network security configuration is defined, you must register it inside your AndroidManifest.xml file. Open the manifest file and locate the application tag. Add the android:networkSecurityConfig attribute pointing to your newly created XML resource.

<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:networkSecurityConfig="@xml/network_security_config" android:theme="@style/Theme.AppCompat.NoActionBar"> <!-- TWA Launcher Activities go here --> </application>

Once applied, compile and run the application. The system will now permit the TWA launcher to communicate with your unencrypted HTTP local development endpoints without raising cleartext security exceptions.

Step 3: Bypassing Digital Asset Links Validation

Even with cleartext traffic permitted, Chrome enforces strict Digital Asset Links checks for TWAs. If the association between your APK signature and the destination web origin cannot be verified, Chrome will show a browser address bar at the top of the viewport. Since a local development server cannot serve a production-signed assetlinks.json file from a public HTTPS endpoint, the address bar will persist. You can disable this validation during development using Android Debug Bridge (ADB).

Connect your testing device or launch an emulator, and execute the following ADB commands via your computer's terminal. This instructs Chrome to skip Digital Asset Links verification for your development package and destination URL:

adb shell am start \ -n com.android.chrome/com.google.android.apps.chrome.Main \ -a android.intent.action.VIEW \ -d "http://localhost:3000" \ --es android.support.customtabs.extra.ASSOCIATION_TOKEN "[\"com.example.twaapp\"]"

Replace com.example.twaapp with your unique application package ID, and adjust http://localhost:3000 to match your current local web server destination. This flag bypasses the verification check on Chrome, removing the browser address bar for a native full-screen test session.

Step 4: Using ADB Port Forwarding for Localhost

If you are testing on a physical device connected via USB rather than an emulator, the domain localhost inside the mobile Chrome instance refers to the mobile device itself, not your computer. To access your computer's local development server (running on port 3000, for example) from your physical device, configure port forwarding via ADB.

adb reverse tcp:3000 tcp:3000

Executing this command redirects all network requests made to localhost:3000 on your mobile device straight to localhost:3000 on your development machine. This enables you to interact with your local development environment using standard localhost URLs, keeping your local configurations simple and consistent.

Step 5: Preparing for Production Releases

Allowing cleartext HTTP and bypassing SSL validation are essential strategies for local iteration, but they represent significant security hazards if left in place for your public build. Google Play rejects apps that allow unrestricted cleartext traffic without a justified cause, and users will see an unverified browser bar if your Asset Links fail.

Configuration SettingDevelopment StageProduction Release
Cleartext TrafficPermitted for local IPs / localhostStrictly Disabled (HTTPS only)
Digital Asset LinksBypassed via ADB commandsStrictly Verified via assetlinks.json
Port ForwardingEnabled (adb reverse)Disabled
Network Security ConfigRequired for local debugging exceptionsRemoved or restricted to secure domains

Before building your final Android App Bundle (AAB) for Google Play distribution, ensure you revert your configurations. Remove the android:networkSecurityConfig attribute from your production manifest, or make sure your configuration only specifies secure domains. Your production build must exclusively target your public HTTPS origin, backed by a valid Digital Asset Links file hosted at https://yourdomain.com/.well-known/assetlinks.json.

Ready to build for Android and iOS?

€49.99 once includes unlimited Android APK and AAB plus iOS IPA builds, all from one dashboard.

Build my app