我希望能够访问 metro.config.js
中的变量。
在 iOS 上,这可以通过在“build设置”选项卡中添加用户定义变量来实现。这可以通过 process.env.MY_VAR
访问。 MY_VAR
的值可以根据正在构建的目标进行更改。
如何使用产品 flavor 在 Android 上实现相同的效果?
这是我当前的设置
flavorDimensions "apps"
productFlavors {
free {
dimension "apps"
}
paid {
dimension "apps"
}
}
执行步骤
运行 iOS 时,我可以从日志中看到项目是在 Packager 启动之前构建的
info Found Xcode workspace "foo.xcworkspace"
info Building (using "xcodebuild -workspace foo.xcworkspace -configuration Debug -scheme foo -destination id=CE408502-CD8C-4467-AE3D-295081CAF132 -derivedDataPath build/foo") <-- Build
▸ Running script '[CP-User] Config codegen'
▸ Compiling ReactNativeConfig.m
▸ Building library libreact-native-config.a
▸ Running script 'Upload Debug Symbols to Sentry'
▸ Running script 'Start Packager <-- Metro starts here
但是,打包程序在我的 gradle 构建任务执行之前启动
info Starting JS server... <-- Metro starts here
info Installing the app...
> Configure project :app
Reading env from: .env
> Task :app:installFreeDebug <-- Build
最佳答案
将以下代码添加到您的 build.gradle
文件中。
buildTypes.each {
it.buildConfigField 'String', 'KEY_STRING', '"Default_Value"'
it.buildConfigField 'int', 'KEY_INT', '0'
}
applicationVariants.all { variant ->
if (variant.productFlavors[0].ext.has("key_1")) {
buildConfigField('String', 'KEY_STRING', variant.productFlavors.get(0).ext.key_1)
}
if (variant.productFlavors[0].ext.has("key_2")) {
buildConfigField('int', 'KEY_INT', variant.productFlavors.get(0).ext.key_2)
}
}
然后将 ext.key_1 = '"desired string value"'
和 ext.key_2 = 'desired integer value'
添加到这样的风格中
flavorDimensions "apps"
productFlavors {
free {
dimension "apps"
ext.key_1 = '"free_value"'
ext.key_2 = '0'
}
paid {
dimension "apps"
ext.key_1 = '"paid_value"'
ext.ket_2 = '100'
}
}
现在,您将通过调用 BuildConfig.KEY_STRING
和 BuildConfig.KEY_INT
来访问应用中的值。
如果您未在风格中为key_1
设置值,则默认值将为“Default_Value”
。
更新
我很惭愧地说我的上述答案是错误的,因为通过这种方式,您可以访问 JS 范围内的 BuildConfig
,但正如您在问题中提到的,您需要访问 Metro Bundler< 中的配置
和 metor.config.js
。我在 metro.config.js
文件的开头添加了 console.log(process.env);
并找出了 process.env
Metro Bundler
是我的操作系统(在我的例子中是 Windows 10)环境变量。因此,这意味着如果您添加所需的变量作为操作系统环境变量,那么您将通过 process.env
在 metro.config.js
中访问它们。我尝试通过 build.gradle
添加环境变量,但这不是一个好方法,因为:
1.我找不到在 Gradle 中添加环境变量的方法
2.如果我可以执行第 1 步,那么正如您提到的,Metro
在 android Build
之前启动,因此配置将晚于准备就绪,Metro
可以'不要访问它们。
所以,我决定用另一种方式来解决这个问题。首先,我更改了 build.gradle
以在构建过程中记录所需的变量。
flavorDimensions "apps"
productFlavors {
free {
dimension "apps"
// Add any configuration you need for free flavor
buildConfigField('String', 'KEY_STRING', '"free_value"')
}
paid {
dimension "apps"
// Add any configuration you need for paid flavor
buildConfigField('String', 'KEY_STRING', '"paid_value1"')
buildConfigField('int', 'KEY_INT', '100')
}
}
applicationVariants.all { variant ->
// Read all flavors configuration
variant.productFlavors.each { flavor ->
flavor.buildConfigFields.each { key, value ->
// Set configuration to variant to be accessible through BuildConfig
variant.buildConfigField(value.type, value.name, value.value)
// Log all configurations in output
println "[" + variant.name + "]---" + value.name + "=" + value.value
}
}
variant.outputs.each { output ->
// For each separate APK per architecture, set a unique version code as described here:
// https://developer.android.com/studio/build/configure-apk-splits.html
def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) { // null for the universal-debug, universal-release variants
output.versionCodeOverride =
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
}
}
}
然后我编写了一个 bat
文件来运行 Gradle 中的 {variant}PreBundle
任务(例如 freeDebugPreBundle)。然后它会读取输出并提取所需的变量,然后将它们设置为环境变量,最后调用 react-native run-android --variant {variant}
命令。
run-android.bat
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
:: Reading input arguments to extract desired variant
FOR %%a IN (%*) do (
set "arg=%%a"
if "!found!"=="true" (
set "variant=%%a"
GOTO:EndOfLoop
)
if "!arg!"=="--variant" set found=true
)
:EndOfLoop
:: User must provide variant because when you have flavors, then `debug` varinat does not exist anymore
if "!variant!"=="" (
echo You must provide --variant
GOTO:EOF
)
:: Creating a pttern to extract required variables
set search=[!variant!]---
:: Creating gradle task name based on input variant
set firstCharUpper=%variant:~0,1%
CALL :UpCase firstCharUpper
set taskName=build!firstCharUpper!%variant:~1%PreBundle
echo Running !taskName!
:: Creating an empty bat file to store environment variables and call later
echo. > custome_env.bat
:: Running gradle task and extracting required variables from output log
cd android
FOR /F "tokens=* USEBACKQ" %%F IN (`gradlew app:!taskName!`) DO (
SET "line=%%F"
SET "newLine=!line:%search%=!"
if not "!line!"=="!newLine!" (
echo !line!
set "keyValue=!line:%search%=!"
:: Adding environment variabel to custome_env.bat file
echo set !keyValue!>>../custome_env.bat
)
)
ENDLOCAL
:: Running custome_env.bat file to set required variables as environment variable
call custome_env.bat
:: Calling react-native command with all input parameters (%*)
call react-native run-android %*
GOTO:EOF
@echo on
:UpCase
:: Subroutine to convert a variable VALUE to all UPPER CASE.
:: The argument for this subroutine is the variable NAME.
FOR %%i IN ("a=A" "b=B" "c=C" "d=D" "e=E" "f=F" "g=G" "h=H" "i=I" "j=J" "k=K" "l=L" "m=M" "n=N" "o=O" "p=P" "q=Q" "r=R" "s=S" "t=T" "u=U" "v=V" "w=W" "x=X" "y=Y" "z=Z") DO CALL SET "%1=%%%1:%%~i%%"
GOTO:EOF
要运行应用程序,您应该运行以下命令:
run-android.bat --variant freeDebug
您也可以使用其他 react-native
选项,但必须提供 --variant
因为当您有风格时,默认变体 debug
不存在。
PS:我不知道你的发布程序是怎样的,所以我不确定这个答案是否与你的发布程序兼容。如果我知道的话也许我可以找到解决方案。
关于android - 从 Android Studio 风格设置 process.env 变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59864875/