Введение: почему Android 9 до сих пор важен (даже в 2025 году)
Представь ситуацию: ты пишешь приложение, которое должно общаться с сервером по старому доброму HTTP. Или тестируешь локальный API на localhost. Запускаешь на Android 9 (Pie) — и получаешь серый экран, ошибку соединения и лог с пугающим словом Cleartext HTTP traffic not permitted. Знакомо?
Android 9 (API 28) стал переломным моментом: Google по умолчанию запретил незащищённые HTTP-соединения. Для разработчиков это стало вызовом. Даже в 2025 году, когда вышли Android 14 и 15, миллионы устройств всё ещё работают на "девятке". Более того, многие корпоративные приложения и legacy-системы вынуждены поддерживать HTTP. Как быть? Как разрешить все типы сетевых соединений HTTP и HTTPS, не нарушив безопасность?
В этой статье мы разберём лучшие практики на Kotlin, которые реально работают в 2025 году. Ты узнаешь не просто "как сделать", а "как сделать правильно" — чтобы и Google Play не заблокировал, и пользователи не пострадали.
Что изменилось в Android 9: краткий экскурс в историю
До Android 8.1 разработчики спокойно использовали HTTP. Но с выходом Pie Google ввёл политику безопасности, которая блокирует cleartext traffic — любой трафик, не зашифрованный через TLS. Это коснулось:
- HTTP-запросов (порт 80);
- WebSocket без шифрования (ws://);
- Некоторых кастомных протоколов.
Исключение — HTTPS (порт 443) и локальный localhost. Но что, если твой сервер всё ещё живёт на HTTP? Или ты разрабатываешь приложение для внутренней сети компании?
Решение — Network Security Configuration. Это XML-файл, который говорит системе: "Эй, этому домену можно доверять". В 2025 году это стандарт де-факто, и мы покажем, как его правильно настроить.
Метод 1: Самый простой способ — отключить проверку для всего приложения
Если ты хочешь разрешить все типы сетевых соединений HTTP и HTTPS для всего приложения (например, для прототипа или тестового билда), можно использовать один флаг в манифесте. Но предупреждаем: для продакшена это плохая практика.
Шаг 1: Добавь атрибут в AndroidManifest.xml
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:usesCleartextTraffic="true">
...
</application>
Шаг 2: Убедись, что targetSdkVersion = 28 или ниже
Если targetSdkVersion >= 28, этот флаг всё ещё работает. Но Google Play может предупредить пользователя о небезопасном приложении. В 2025 году лучше комбинировать этот метод с более тонкой настройкой.
Плюсы: быстро, работает для всех доменов.
Минусы: уязвимость для MitM-атак, не пройдёшь модерацию Google Play.
Метод 2: Правильный путь через Network Security Config (2025 Edition)
Этот метод — золотой стандарт. Ты создаёшь XML-файл, в котором указываешь, какие домены и протоколы разрешены. В 2025 году мы рекомендуем использовать его для всех новых проектов.
Шаг 1: Создай файл res/xml/network_security_config.xml
Вот пример, который разрешает все HTTP и HTTPS для любого домена (но с ограничениями):
<?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>
Шаг 2: Подключи конфиг в AndroidManifest
<application
android:networkSecurityConfig="@xml/network_security_config"
...>
</application>
Готово! Теперь все соединения HTTP и HTTPS разрешены. Но это всё ещё слишком широко. Для production лучше ограничить конкретными доменами.
Тонкая настройка: разрешить только для определённых доменов
Допустим, твой сервер — api.example.com. Вот как разрешить HTTP только для него:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">example.com</domain>
<domain includeSubdomains="true">localhost</domain>
</domain-config>
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
Этот код запрещает cleartext traffic для всех доменов, кроме example.com и localhost. Идеально для разработки и продакшена.
Метод 3: Программное разрешение через Kotlin (для динамических сценариев)
Иногда нужно разрешить HTTP только в определённых условиях — например, при тестировании. Kotlin позволяет сделать это динамически через OkHttpClient или URLConnection. Вот пример для OkHttp (библиотека, которая используется в 80% Android-проектов):
import okhttp3.OkHttpClient
import okhttp3.ConnectionSpec
import java.util.Arrays
val client = OkHttpClient.Builder()
.connectionSpecs(Arrays.asList(
ConnectionSpec.MODERN_TLS,
ConnectionSpec.COMPATIBLE_TLS,
ConnectionSpec.CLEARTEXT // Разрешает HTTP
))
.build()
Но помни: этот подход работает только для запросов, сделанных через этот конкретный клиент. Если в приложении есть другие HTTP-библиотеки (например, Retrofit на другом OkHttp), их тоже нужно настроить.
Когда использовать: если ты хочешь временно разрешить HTTP для отладки, но в продакшене оставить HTTPS. Просто переключай ConnectionSpec.CLEARTEXT в зависимости от BuildConfig.DEBUG.
Безопасность в 2025: что нужно помнить
Разрешение всех сетевых соединений HTTP и HTTPS — это как открыть все двери в доме. Да, удобно. Но опасно. Вот три правила, которые спасут твоё приложение:
- Не используй
usesCleartextTraffic="true"в продакшене. Это флаг для тестов. В 2025 году Google Play может отклонить апдейт, если увидит его без веской причины. - Добавь сертификаты для HTTPS