Как разрешить все типы сетевых подключений HTTP и HTTPS в Android 9 (Pie) на Kotlin?
Решение: настройка Network Security Configuration для Android 9 (Pie)
Проблема, с которой вы столкнулись, связана с изменениями в безопасности Android 9 (API 28). Google ввел строгие правила по умолчанию: разрешен только зашифрованный трафик (HTTPS). Для HTTP-запросов нужно явно настроить исключения. Ваш подход с android:usesCleartextTraffic="true" должен работать, но часто он не помогает, если не сбросить кэш или не переустановить приложение. Давайте рассмотрим правильное решение через файл конфигурации сети.
Шаг 1: Создайте файл network_security_config.xml
Создайте в ресурсах вашего проекта папку res/xml (если её нет) и добавьте файл network_security_config.xml со следующим содержимым:
<?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>
Этот конфиг разрешает HTTP-трафик (cleartext) для всех доменов и доверяет системным сертификатам (для HTTPS). Если вы хотите разрешить только для конкретных доменов, используйте <domain-config>:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">my-test-server.com</domain>
</domain-config>
</network-security-config>
Шаг 2: Укажите конфигурацию в AndroidManifest.xml
Добавьте атрибут android:networkSecurityConfig в тег <application>:
<application
android:networkSecurityConfig="@xml/network_security_config"
... >
...
</application>
Шаг 3: Очистите кэш и переустановите приложение
После внесения изменений обязательно выполните очистку проекта (Build → Clean Project) и переустановите приложение на устройстве или эмуляторе. Простое обновление может не сработать, так как Android кэширует конфигурацию безопасности.
Альтернативный способ: android:usesCleartextTraffic
Если вы предпочитаете более простой (но менее гибкий) подход, добавьте в <application>:
<application
android:usesCleartextTraffic="true"
... >
...
</application>
Это разрешит HTTP для всех доменов. Однако этот метод не дает тонкой настройки и может быть не рекомендован для продакшена.
Проверка работы
После настройки ваш код на Kotlin будет работать без ошибок:
val retrofit = Retrofit.Builder()
.baseUrl("http://my-test-server.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
// Запрос
CoroutineScope(Dispatchers.IO).launch {
val response = apiService.getData()
if (response.isSuccessful) {
Log.d("SUCCESS", "Data: ${response.body()}")
}
}
Важно: Для продакшена используйте только HTTPS и настройте <domain-config> для конкретных доверенных доменов. Полное отключение проверки безопасности делает приложение уязвимым для атак "человек посередине" (MITM).
Альтернативный подход: программное разрешение через NetworkSpecifier
Если вам нужно разрешить HTTP-трафик только для определенных запросов или в коде (например, для библиотек, которые не поддерживают XML-конфигурацию), можно использовать NetworkSpecifier и ConnectivityManager. Однако этот способ сложнее и подходит для редких случаев.
Вот пример, как программно указать, что приложение может использовать HTTP для конкретного URL:
import android.net.*
import android.content.Context
fun allowCleartextForUrl(context: Context, url: String) {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val request = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build()
connectivityManager.registerNetworkCallback(request, object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
// Сеть доступна, можно отправлять HTTP-запросы
Log.d("NETWORK", "Network available for HTTP")
}
})
}
Но помните: этот метод не отключает проверку безопасности полностью. Он лишь помогает управлять сетевыми подключениями. Для решения вашей основной проблемы (ошибка Cleartext HTTP) лучше использовать network_security_config.xml.
Дополнительно: Если вы используете эмулятор Android, убедитесь, что у него есть доступ к интернету и что вы не используете localhost (вместо этого используйте 10.0.2.2 для доступа к хосту).