Introduction: Why Android 9 is Still Important (Even in 2025)
Imagine this: you're writing an app that needs to communicate with a server over good old HTTP. Or you're testing a local API on localhost. You run it on Android 9 (Pie) — and get a gray screen, a connection error, and a log with the frightening word Cleartext HTTP traffic not permitted. Sound familiar?
Android 9 (API 28) was a turning point: Google banned unencrypted HTTP connections by default. This became a challenge for developers. Even in 2025, with Android 14 and 15 released, millions of devices are still running on "nine". Moreover, many enterprise applications and legacy systems are forced to support HTTP. What to do? How to allow all types of network connections HTTP and HTTPS without compromising security?
In this article, we'll break down the best practices in Kotlin that actually work in 2025. You'll learn not just "how to do it", but "how to do it right" — so that Google Play doesn't block it and users don't suffer.
What Changed in Android 9: A Brief History Lesson
Before Android 8.1, developers freely used HTTP. But with the release of Pie, Google introduced a security policy that blocks cleartext traffic — any traffic not encrypted via TLS. This affected:
- HTTP requests (port 80);
- Unencrypted WebSocket (ws://);
- Some custom protocols.
The exception is HTTPS (port 443) and local localhost. But what if your server still lives on HTTP? Or you're developing an app for a company's internal network?
The solution is Network Security Configuration. This is an XML file that tells the system: "Hey, this domain can be trusted." In 2025, this is the de facto standard, and we'll show you how to configure it correctly.
Method 1: The Simplest Way — Disable Verification for the Entire App
If you want to allow all types of network connections HTTP and HTTPS for the entire app (for example, for a prototype or test build), you can use one flag in the manifest. But be warned: for production, this is bad practice.
Step 1: Add the attribute to AndroidManifest.xml
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:usesCleartextTraffic="true"> ...</application>Step 2: Make sure targetSdkVersion = 28 or lower
If targetSdkVersion >= 28, this flag still works. But Google Play may warn the user about an unsafe app. In 2025, it's better to combine this method with more granular configuration.
Pros: fast, works for all domains.
Cons: vulnerable to MitM attacks, won't pass Google Play moderation.
Method 2: The Right Way via Network Security Config (2025 Edition)
This method is the gold standard. You create an XML file specifying which domains and protocols are allowed. In 2025, we recommend using it for all new projects.
Step 1: Create the file res/xml/network_security_config.xml
Here's an example that allows all HTTP and HTTPS for any domain (but with restrictions):
<?xml version="1.0" encoding="utf-8"?><network-security-config> <base-config cleartextTrafficPermitted="true"> <trust-anchors> <certificates src="system" /> </trust-anchors> </base-config></network-security-config>Step 2: Connect the config in AndroidManifest
<application android:networkSecurityConfig="@xml/network_security_config" ...></application>Go