Как добавить network_security_config.xml в манифест в приложении expo без извлечения

Я создаю приложение с выставкой.
Использование Axios для обработки запросов.
API имеет самоподписанные сертификаты.
Запросы не выполняются на Android 7 (они работают на Android 9)

Я прочитал в Интернете, что мне нужно добавить network_security_config.xml в манифест Android. Связь.

Как я могу сделать это на выставке (вероятно, app.json) без извлечения?

Спасибо !

5
0
676
1

Ответы 1

Я столкнулся с аналогичной проблемой (необходимо было подключиться к локальному API с самозаверяющим сертификатом), и после смехотворного количества исследований и экспериментов я, наконец, смог найти решение. Вам нужно будет создать плагин конфигурации, для чего требуется Expo SDK версии 41+. Обратите внимание, что вы потеряете возможность использовать Expo Go, но останетесь в управляемом рабочем процессе (т. е. вам не нужно будет изменять собственный код), и вы сможете использовать сборки EAS для создания пользовательский клиент для разработчиков, который по сути представляет собой версию Expo Go, адаптированную для ваш проект.

Добавьте сертификат в список пользовательских сертификатов вашего устройства:

(Этот шаг, вероятно, не нужен, если вы включаете свой (необработанный) сертификат в приведенную ниже конфигурацию сети, см. эта ссылка.) Перейдите к Settings -> Security -> Advanced -> Encryption & credentials -> Install a certificate, чтобы импортировать сертификат

Убедитесь, что сертификат действительно является проблемой:

try {
    const response = await axios.post(urlPath, payload);
} catch (error) {
    console.error(error.request?._response);
}

Вы узнаете, что ваше приложение не доверяет сертификату, если вы получите сетевую ошибку и error.request._response прочитаете java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

Создайте плагин:

Теперь вы создадите плагин конфигурации, который в основном представляет собой функции JS, которые запускаются на этапе prebuild Expo для изменения собственной конфигурации, такой как манифест Android, перед созданием собственного проекта.

В корне вашего проекта создайте папку plugins со следующими двумя файлами:

  • network_security_config.xml:
<?xml version = "1.0" encoding = "utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted = "true">
        <trust-anchors>
            <certificates src = "system" />
            <certificates src = "user" />
        </trust-anchors>
    </base-config>
</network-security-config>
  • trust-local-certs.js:
const {AndroidConfig, withAndroidManifest } = require('@expo/config-plugins');
const {Paths} = require('@expo/config-plugins/build/android');
const path = require('path');
const fs = require('fs');
const fsPromises = fs.promises;

const { getMainApplicationOrThrow} = AndroidConfig.Manifest

const withTrustLocalCerts = config => {
    return withAndroidManifest(config, async config => {
        config.modResults = await setCustomConfigAsync(config, config.modResults);
        return config;
    });
}

async function setCustomConfigAsync(
    config,
    androidManifest
) {

    const src_file_pat = path.join(__dirname, "network_security_config.xml");
    const res_file_path = path.join(await Paths.getResourceFolderAsync(config.modRequest.projectRoot),
        "xml", "network_security_config.xml");

    const res_dir = path.resolve(res_file_path, "..");

    if (!fs.existsSync(res_dir)) {
        await fsPromises.mkdir(res_dir);
    }

    try {
        await fsPromises.copyFile(src_file_pat, res_file_path);
    } catch (e) {
        throw e;
    }

    const mainApplication = getMainApplicationOrThrow(androidManifest);
    mainApplication.$["android:networkSecurityConfig"] = "@xml/network_security_config";

    return androidManifest;
}

module.exports = withTrustLocalCerts;

Запустите expo prebuild и свяжите плагин

Чтобы использовать плагин, у вас должен быть файл с именем app.json в корне проекта. Я не уверен на 100%, откуда я взял файл, но я считаю, что он был создан автоматически при первом запуске expo prebuild. Примечание:

  • Я рекомендую обновить Expo SDK до самой последней версии (в настоящее время 44), потому что теперь команда prebuild (которая, по-видимому, такая же, как eject) теперь полностью обратима (например, она не устанавливает большинство дополнительных зависимостей, к которым привыкла). .
  • Предварительная сборка создаст собственные папки, но вы можете безопасно удалить эти папки после завершения настройки плагина (вам действительно следует удалить их, если вы хотите остаться в управляемом рабочем процессе! Когда вы запускаете сборку EAS, EAS примет на себя голый рабочий процесс, если он видит собственные папки и, предположительно, не запускает ваш плагин снова).
  1. Запустите expo prebuild и следуйте инструкциям -> Это должно создать файл app.json.
  2. Удалите сгенерированную родную папку androidios, если она тоже была создана).
  3. В app.json добавьте следующее в конец ключа expo:
    "plugins": [
      "./plugins/trust-local-certs.js"
    ]   
    
  4. Запустите expo prebuild --no-install и убедитесь, что android/app/src/main/AndroidManifest.xml содержит ссылку на конфигурацию вашей сети, и что android/app/src/main/res/xml/network_security_config.xml был правильно скопирован из вашего каталога plugins.
  5. Если все хорошо, ваш плагин настроен правильно и вам следует снова удалить родные папки (см. примечание выше).

Настройте и запустите сборку EAS:

Если вы еще этого не сделали, настройте свой проект для сборок EAS с помощью следующий эти инструкции (установите интерфейс командной строки EAS, запустите eas build:configure и настройте профиль разработчика в eas.json). Затем бегите eas build --profile development --platform android. Это создаст собственный клиент для разработчиков в облаке (плагин будет запущен на этапе prebuild), который вы сможете установить на свое устройство и который заменит Expo Go. Чтобы запустить сервер метро, ​​запустите expo start --dev-client. После этого ваш клиент разработчика сможет подключиться к серверу Metro, и если вы снова запустите запрос axios, он должен пройти :)

Обратите внимание, что изначально я пытался встроить конфигурацию сети в манифест Android, чтобы не связываться с файлами ресурсов. К сожалению, мне пока не удалось заставить его работать (см. stackoverflow.com/q/70769075/4350421)

silentsurfer 19.01.2022 19:18

Другие вопросы по теме