How to add network_security_config.xml to manifest in expo app without ejecting(如何在不弹出的情况下将 network_security_config.xml 添加到 expo 应用程序中的清单)
问题描述
我正在使用 expo 构建一个应用程序.
使用 Axios 处理请求.
该 API 具有自签名证书.
请求在 android 7 上失败(它们在 android 9 上工作)
I'm building an app with expo.
Using Axios to handle the requests.
The API has a self-signed certificates.
Requests fail on android 7 (they work on android 9)
我在网上看到我需要将 network_security_config.xml
添加到 android 清单中.链接.
I read online that I need to add a network_security_config.xml
to the android manifest. Link.
如何在不弹出的情况下在 expo(可能是 app.json)中做到这一点?
How can I do this in expo (probably app.json) without ejecting ?
谢谢!
推荐答案
我遇到了类似的问题(需要使用自签名证书连接到本地 API),经过大量的研究和实验,我终于能够找到解决方案.您需要创建一个 配置插件,这需要Expo SDK 版本 41+.请注意,您将失去使用 Expo Go 的能力,但您将保留在托管工作流程中(即无需更改本机代码),并且您可以使用 EAS 构建来构建 自定义开发客户端,基本上是为您的项目量身定制的 Expo Go 版本.
I was facing a similar problem (needed to connect to a local API with self-signed certificate) and after a ridiculous amount of research and experimentation I was finally able to find a solution. You will need to create a config plugin, which requires Expo SDK version 41+. Note that you will lose the ability to use Expo Go, but you will remain in the managed workflow (i.e. no need to change native code) and you can use EAS builds to build a custom dev client, which is basically a version of Expo Go tailored to your project.
将证书添加到您设备的用户证书列表中:
(如果您在下面的网络配置中包含您的(原始)证书,则此步骤可能是不必要的,请参阅 此链接.) 转到 Settings ->安全 ->高级->加密与凭据->安装证书
导入证书
确保证书确实是问题所在:
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,您将知道您的应用不信任证书找不到路径.
You'll know your app doesn't trust the certificate if you get a network error and error.request._response
reads java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
创建插件:
您现在将创建一个配置插件,它基本上是在 Expo 的 prebuild
阶段运行的 JS 函数,用于在构建原生项目之前修改原生配置,例如 Android 清单.
You will now create a config plugin, which are basically JS functions which run during Expo's prebuild
phase to modify native configuration such as the Android manifest before building the native project.
在您的项目根目录中,创建一个 plugins
文件夹,其中包含以下两个文件:
In your project root, create a plugins
folder with the following two files:
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
&链接插件
Run expo prebuild
& link the plugin
为了使用插件,您必须在项目根目录中有一个名为 app.json
的文件.我不能 100% 确定我从哪里得到文件,但我相信它是在我第一次运行 expo prebuild
时自动创建的.注意:
In order to use the plugin, you have to a have a file called app.json
in the project root. I'm not 100% sure where I got the file from, but I believe it was created automatically when I first ran expo prebuild
. Note:
- 我建议将 Expo SDK 升级到最新版本(当前为 44),因为现在
prebuild
命令(显然与eject
相同)现在已经完全可逆的(例如,它不会安装以前的大部分附加依赖项). - Prebuild 将创建本机文件夹,但您可以在完成插件设置后安全地删除这些文件夹(如果您想保留在托管工作流中,您确实应该删除它们!当您运行 EAS 构建时,EAS如果它看到本机文件夹,它将假定裸工作流,并且可能不会再次运行您的插件).
- I recommend upgrading the Expo SDK to the most current version (currently 44), because now the
prebuild
command (which apparently is the same aseject
) is now completely reversible (e.g. it doesn't install most of the additional dependencies it used to). - Prebuild will create the native folders, but you can safely delete these folders once you are done setting up the plugin (You really should delete them, if you want to remain in the managed workflow! When you run an EAS build, EAS will assume the bare workflow if it sees the native folders, and presumably not run your plugin again).
- 运行
expo prebuild
并按照提示操作 ->这应该会创建app.json
文件. - 删除生成的原生
android
文件夹(以及ios
,如果它也已创建). - 在
app.json
中,将以下内容添加到expo
键的末尾:
- Run
expo prebuild
and follow the prompts -> This should create theapp.json
file. - Delete the generated native
android
folder (andios
, if it got created as well). - In
app.json
, add the following to the end of theexpo
key:
"plugins": [
"./plugins/trust-local-certs.js"
]
expo prebuild --no-install
并检查 android/app/src/main/AndroidManifest.xml
是否包含对您的网络配置的引用,并且 android/app/src/main/res/xml/network_security_config.xml
已从您的 plugins
目录正确复制.
expo prebuild --no-install
and check that android/app/src/main/AndroidManifest.xml
contains a reference to your network config, and that android/app/src/main/res/xml/network_security_config.xml
was correctly copied over from your plugins
directory.设置并运行 EAS 构建:
如果您还没有这样做,请按照以下步骤为 EAS 构建设置您的项目这些说明(安装 EAS CLI,运行 eas build:configure
并在 eas.json
中配置开发配置文件).然后,运行 eas build --profile development --platform android
.这将在云中创建一个自定义开发客户端(在 prebuild
阶段运行插件),您可以将其安装在您的设备上并充当 Expo Go 的替代品.要启动 Metro 服务器,请运行 expo start --dev-client
.然后,您的开发客户端应该能够获取到 Metro 服务器的连接,如果您再次运行 axios 请求,它应该会通过:)
If you haven't done so already, set up your project for EAS builds by following
these instructions (install EAS CLI, run eas build:configure
and configure a dev profile in eas.json
). Then, run eas build --profile development --platform android
. This will create a custom dev client in the cloud (running the plugin during the prebuild
phase), which you can install on your device and acts as a replacement for Expo Go. To start the metro server, run expo start --dev-client
. Your dev client should then be able to pick up the connection to the Metro server and if you run the axios request again, it should go through :)
这篇关于如何在不弹出的情况下将 network_security_config.xml 添加到 expo 应用程序中的清单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何在不弹出的情况下将 network_security_config.xml 添加到 expo 应用程序中的清单
基础教程推荐
- android 应用程序已发布,但在 google play 中找不到 2022-01-01
- Kivy Buildozer 无法构建 apk,命令失败:./distribute.sh -m “kivy"d 2022-01-01
- 如何在 UIImageView 中异步加载图像? 2022-01-01
- 当从同一个组件调用时,两个 IBAction 触发的顺序是什么? 2022-01-01
- 如何让对象对 Cocos2D 中的触摸做出反应? 2022-01-01
- Android:对话框关闭而不调用关闭 2022-01-01
- UIWebView 委托方法 shouldStartLoadWithRequest:在 WKWebView 中等效? 2022-01-01
- 如何在没有IB的情况下将2个按钮添加到右侧的UINavigationbar? 2022-01-01
- 在 gmail 中为 ios 应用程序检索朋友的朋友 2022-01-01
- 如何在 iPhone 上显示来自 API 的 HTML 文本? 2022-01-01