Ви випустили нову збірку, перейшли на VPN, і той самий екран перестав завантажуватися. На Android 9 і новіших частіше пояснення нудніше: платформа відмовляє у звичайному HTTP застосункам, націленим на API 28 або вище, а VPN змінив лише стільки контексту, щоб це проявилося. Помилка, яку ви бачите, залежить від HTTP-клієнта, тому він так рідко каже cleartext.

Що це насправді за збій

Починаючи з Android 9 платформа за замовчуванням блокує cleartext, щойно застосунок націлений на рівень API 28 або вищий. Запит до звичайної HTTP-адреси відхиляється платформою раніше, ніж з пристрою вийде бодай один пакет. Яку помилку ви побачите, залежить від бібліотеки HTTP: іноді загальний збій мережі, іноді тайм-аут, іноді повідомлення, що прямо називає cleartext. Чого він не робить ніколи — не доходить до вашого сервера. Android документує типову поведінку й альтернативу з обмеженням за доменом у посібнику з налаштування безпеки.

Браузер на тому самому пристрої все ще може завантажити сторінку, і це та підказка, яку більшість пропускає. Браузери не підпорядковуються мережевій політиці безпеки вашого застосунку.

Чому звинувачують VPN

Зазвичай три речі змінюються одночасно. Після підключення VPN застосунок може розв’язувати інше ім’я хоста, пристрій може бути новим із новішою збіркою, або сама збірка могла перейти на цільовий рівень API, що вмикає типову поведінку. VPN видно, а цільовий SDK ні, тому заявку отримує VPN.

Порівняйте цільові рівні старої та нової збірки, перш ніж чіпати мережеву конфігурацію. Застосунок, націлений на 27 або нижче, звільнений, і це пояснює кожне повідомлення «у мене працює на старому телефоні».

Де насправді опиняється прапорець Expo

У керованому проєкті Expo додавання налаштування до app.json не редагує маніфест Android, бо маніфест створюють prebuild і збірки для розробки. Саме плагін конфігурації записує налаштування на цьому етапі. Підтримуваний шлях — expo-build-properties, налаштований у конфігурації застосунку з опцією cleartext під android.

{
  "plugins": [
    ["expo-build-properties", {
      "android": { "usesCleartextTraffic": true }
    }]
  ]
}

Фрагмент задає лише опцію плагіна; маніфест створюється пізніше. Запустіть prebuild або свіжу збірку клієнта розробки, а потім перед повторним тестом перегляньте створений AndroidManifest.xml щодо android:usesCleartextTraffic, бо перезавантаження лише через JS зберігає старий маніфест. Узгодьте версію плагіна з Expo SDK, на якому працює проєкт. Опції плагіна змінюються між випусками, а фрагмент, скопійований з іншого SDK, — надійне джерело тихого недороблення.

Bare-процес і вужчий варіант

Для bare React Native відповідником є android:usesCleartextTraffic на елементі application або конфігурація мережевої безпеки, що дозволяє cleartext лише для названих доменів. Перевагу варто віддати формі з обмеженням за доменом, бо вона дозволяє внутрішній API і залишає все інше на HTTPS. Вона також документує власний список винятків, і саме про цю частину запитає рецензент.

Жоден із підходів не змінює типову поведінку платформи для того, що ви не назвали.

Спершу доведіть це за журналом пристрою

Перш ніж редагувати конфігурацію, отримайте точний збій. adb logcat на під’єднаному пристрої показує відмову платформи в cleartext і називає компонент, який її спричинив. Відкинутий сокет, ім’я, що не розв’язується, або невдале рукостискання TLS вказують зовсім в інше місце, а ввімкнення cleartext лише без користі послабило б застосунок.

Далі тримайте продакшн чесним. Cleartext прийнятний для лабораторної кінцевої точки, яка не може запропонувати TLS, і лише на найкоротший час, який ви можете спланувати. Якщо API може завершувати TLS усередині приватної мережі, покладіть сертифікат у сховище довіри пристрою й залиште cleartext вимкненим, бо тунель шифрує шлях до свого виходу і нічого після нього.

Щойно кінцева точка почне відповідати через HTTPS, приберіть дозвіл, перезберіть і перевірте на VPN і на звичайному Wi-Fi в одному сеансі. Розв’язання імен може відрізнятися на цих двох шляхах, і лише пара скаже, котрий каже правду.

Схожі статті