3

我希望能够访问我的metro.config.js.

在 iOS 上,这可以通过在 Build Settings 选项卡中添加用户定义的变量来实现。这可以通过process.env.MY_VAR. 的值MY_VAR可以根据正在构建的目标进行更改。

如何使用产品风格为 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 build 任务执行之前启动

info Starting JS server...                    <-- Metro starts here
info Installing the app...
> Configure project :app
Reading env from: .env
> Task :app:installFreeDebug                  <-- Build
4

1 回答 1

2

将以下代码添加到您的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".



更新
我很惭愧地说我的上述答案是错误的,因为通过这种方式您可以访问BuildConfigin JS 范围,但正如您在问题中提到的那样,您需要访问Metro Bundlerand中的配置metor.config.js。我在文件console.log(process.env);的开头添加了 ,metro.config.js并找出了process.envMetro Bundler的操作系统(在我的情况下为 Windows 10)环境变量。所以这意味着如果您将所需的变量添加为操作系统环境变量,那么您将metro.config.js通过process.env. 我尝试通过添加环境变量,build.gradle但这不是一个好方法,因为:
1.我找不到在 Gradle
2 中添加环境变量的方法。如果我可以做第 1 步,那么正如你提到的Metroandroid 之前的开始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文件来{variant}PreBundle在 Gradle 中运行任务(例如 freeDebugPreBundle)。然后它将读取输出并提取所需的变量,然后将它们设置为环境变量,最后调用react-native run-android --variant {variant}命令。
运行-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:我不知道您的发布程序如何,所以我不确定这个答案是否与您的发布程序兼容。如果我知道,也许我可以找到解决方案。

于 2020-01-25T01:35:23.957 回答