Keywords: Android Security | HTTP Traffic Restriction | Network Security Configuration
Abstract: This article provides an in-depth analysis of the technical background and root causes of cleartext HTTP traffic restrictions in Android 8 and later versions. It details four effective solutions: upgrading to HTTPS, configuring network security files, setting usesCleartextTraffic attribute, and adjusting targetSandboxVersion. With complete code examples and configuration instructions, it helps developers thoroughly resolve cleartext HTTP traffic restriction issues while ensuring application compatibility and security across different Android versions.
Problem Background and Technical Analysis
With the continuous improvement of Android system security, Google has strengthened security requirements for network communication in Android 8 (API level 26) and subsequent versions. One of the most significant changes is the restriction on cleartext HTTP traffic, which directly affects numerous applications that rely on HTTP protocol for data exchange.
From a technical perspective, the Android system manages network communication security through the Network Security Policy mechanism. In Android 8, the system by default prohibits applications from sending cleartext HTTP requests, which is implemented through the CleartextURLFilter in the OkHttp library. When an application attempts to establish an HTTP connection, the system calls the checkURLPermitted method for permission verification. If the target URL uses HTTP protocol and doesn't have explicit authorization, an IOException is thrown.
It's important to note that this restriction becomes even stricter in Android 9 (API level 28). According to official documentation, cleartext traffic support is disabled by default starting from Android 9, meaning developers must actively configure to allow HTTP communication.
Detailed Solutions
Solution 1: Upgrade to HTTPS Protocol
The most ideal solution is to upgrade backend services to HTTPS protocol. HTTPS protects data transmission security through TLS/SSL encryption technology, not only solving cleartext traffic restriction issues but also enhancing the overall security level of the application.
In terms of code implementation, simply replace the original HTTP URL with HTTPS URL:
// Original HTTP connection
String url = "http://api.example.com/data";
// Upgrade to HTTPS connection
String secureUrl = "https://api.example.com/data";
// Establish secure connection using OkHttpClient
OkHttpClient client = new OkHttpClient.Builder()
.build();
Request request = new Request.Builder()
.url(secureUrl)
.build();
// Execute network request
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
String responseData = response.body().string();
// Process response data
}
}If backend services cannot support HTTPS temporarily, consider the following alternative solutions.
Solution 2: Configure Network Security Policy
By creating a network security configuration file, you can allow cleartext HTTP traffic for specific domains. This method provides more granular control, solving compatibility issues while maintaining appropriate security levels.
First, create the network_security_config.xml file in the res/xml directory:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">api.example.com</domain>
<domain includeSubdomains="true">192.168.1.100</domain>
</domain-config>
</network-security-config>Then reference this configuration file in AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>Solution 3: Globally Allow Cleartext Traffic
For development stages or internal testing environments, you can globally allow cleartext HTTP traffic by setting the android:usesCleartextTraffic attribute:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:usesCleartextTraffic="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>It's important to note that this method reduces the overall security of the application and is not recommended for production environments.
Solution 4: Adjust Sandbox Version
If the android:targetSandboxVersion attribute is set in the application, it may affect the default behavior of cleartext traffic. In sandbox version 2, the default value of usesCleartextTraffic is false, which may prevent normal HTTP connections even if related attributes are set.
The solution is to set targetSandboxVersion to 1:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app"
android:targetSandboxVersion="1">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>Best Practice Recommendations
In actual development, it's recommended to choose appropriate solutions based on specific scenarios: for production environments, prioritize upgrading to HTTPS protocol; for development and testing environments, use network security configuration files to allow cleartext traffic for specific IP addresses or domains; for quick functional verification, temporarily use the global cleartext traffic allowance method.
Additionally, it's recommended to add version detection logic in code, adopting different network strategies based on different Android versions:
public class NetworkUtils {
public static boolean isCleartextTrafficPermitted() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return NetworkSecurityPolicy.getInstance().isCleartextTrafficPermitted();
}
return true; // Android 7 and below versions allow cleartext traffic by default
}
public static void checkNetworkSecurity() {
if (!isCleartextTrafficPermitted()) {
Log.w("NetworkSecurity", "Cleartext traffic is not permitted on this device");
// Can trigger fallback logic or display user prompts here
}
}
}Through reasonable configuration and code implementation, developers can ensure application compatibility across different Android versions while maintaining security.