android - 从 Android Studio 风格设置 process.env 变量

标签 android react-native android-flavors

我希望能够访问 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_STRINGBuildConfig.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.envmetro.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/

相关文章:

react-native - Jest : How to fix - TypeError: Cannot assign to read only property 'name' of function 'function ()

android - ViewBinding - 不同风格的布局资源

Eclipse 3.5.2 中 Android ninepatch 图像错误

react-native - react native 输入文本 RTL

java - 如何知道当前运行的应用程序是android中的某个消息应用程序

javascript - 如何在 react native 中单击按钮打开 react native 模式?

android BuildConfig.BUILD_TYPE 始终处于发布状态

android - 在查看时 Gradle 警告 : Could not find google-services. json

android - 耗时的操作在什么地方开新线程比较好?

android - Kotlin 通用抽象函数