-
Notifications
You must be signed in to change notification settings - Fork 660
Description
Empty Config object in one of android build flavors invoked with --appIdSuffix
Hello there. I'm created two build flavors for have two builds of my react native application. While I run production flavor in debug mode, Config
object is populated with correct values, while Config
object is empty in staging build.
I have tried to fix issue with different build configs and settings, but even suggestions from AI (gemini) not result to obtain correct Config
in staging build. If there missing some other info - please let me now, I will add ASAP.
I would appreciate any help, thank you in advice.
For my application there will be two buildId
production: health.company.myapp
staging: health.company.myapp.staging
Log of Config object for production debug build:
{"AMPLITUDE_API_KEY": "abc123", "APPLICATION_ID": "health.company.myapp", "APP_ENV": "production", "BUILD_TYPE": "debug", "DEBUG": true, "FLAVOR": "production", "IS_HERMES_ENABLED": true, "IS_NEW_ARCHITECTURE_ENABLED": false, "VERSION_CODE": 1, "VERSION_NAME": "0.0.1", "getConstants": [Function anonymous]}
this is log of Config object for staging build:
{}
Versions of RN and modules used:
node 22.17.1
yarn 4.9.2
react 18.2.0
react-native 0.75.5
react-native-config 1.5.9
App invoked by yarn scripts:
"android:runStagingDebug": "cross-env ENVFILE=.env.staging npx react-native run-android --mode=stagingDebug --appIdSuffix staging",
"android:runStagingRelease": "cross-env ENVFILE=.env.staging npx react-native run-android --mode=stagingRelease --appIdSuffix staging",
"android:runProductionDebug": "cross-env ENVFILE=.env.production npx react-native run-android --mode=productionDebug",
Bellow content of some files I think need to be verified:
/app/build.gradle:
apply plugin: "com.android.application"
apply plugin: "org.jetbrains.kotlin.android"
apply plugin: "com.facebook.react"
apply plugin: 'com.google.gms.google-services'
react {
debuggableVariants = ["debug", "stagingDebug", "productionDebug"]
autolinkLibrariesWithApp()
}
def enableProguardInReleaseBuilds = true
def jscFlavor = 'org.webkit:android-jsc:+'
project.ext.envConfigFiles = [
productionDebug: "../../.env.production",
productionRelease: "../../.env.production",
// stagingDebug: "../../.env.staging", // Handled manually for staging flavor
// stagingRelease: "../../.env.staging" // Handled manually for staging flavor
]
println("Current project.ext.envConfigFiles: " + project.ext.envConfigFiles)
android {
flavorDimensions "environment"
ndkVersion rootProject.ext.ndkVersion
compileSdk rootProject.ext.compileSdkVersion
namespace "health.company.myapp"
defaultConfig {
applicationId "health.company.myapp"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "0.0.1"
}
signingConfigs {
debug {
storeFile file('debug.keystore')
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
}
applicationVariants.all { variant ->
if (variant.name == "stagingDebug" || variant.name == "stagingRelease") {
def envFile = project.ext.envConfigFiles.get(variant.name) // This will now be null for staging
println "For staging variant ${variant.name}, configured env file in project.ext.envConfigFiles is: ${envFile}"
}
}
productFlavors {
staging {
dimension "environment"
applicationId "health.company.myapp.staging"
resValue "string", "app_name", "MyApp Staging"
// build_config_package is still useful as a hint for other tools, or if RNC tries to read it.
resValue "string", "build_config_package", "health.company.myapp.staging"
versionCode 100000 + android.defaultConfig.versionCode
versionName "100001.0.1-staging"
// Manually load .env.staging for this flavor
def stagingEnvFilePath = "../../.env.staging"
def stagingEnvFile = file(stagingEnvFilePath) // Resolve file relative to this build.gradle
if (stagingEnvFile.exists()) {
println "Manually loading .env.staging for 'staging' flavor from ${stagingEnvFile.absolutePath}"
stagingEnvFile.eachLine { line ->
line = line.trim()
if (line.startsWith("#") || line.isEmpty() || !line.contains("=")) {
return // Skip comments, empty lines, or lines without '='
}
def parts = line.split("=", 2)
if (parts.length == 2) {
def key = parts[0].trim()
def value = parts[1].trim()
if ((value.startsWith("\"") && value.endsWith("\"")) || (value.startsWith("'") && value.endsWith("'"))) {
value = value.substring(1, value.length() - 1)
}
println " + Adding buildConfigField from .env.staging: ${key} = ${value}"
buildConfigField "String", "${key}", "\"${value.replace("\"", "\\\"")}\""
}
}
} else {
println "WARN: .env.staging file not found at ${stagingEnvFile.absolutePath} (path was ${stagingEnvFilePath}) for manual loading."
}
}
production {
dimension "environment"
applicationId android.defaultConfig.applicationId
resValue "string", "app_name", "MyApp"
resValue "string", "build_config_package", "health.company.myapp"
versionCode android.defaultConfig.versionCode
versionName android.defaultConfig.versionName
}
}
sourceSets {
staging {
java.srcDirs = ['src/staging/java']
manifest.srcFile 'src/staging/AndroidManifest.xml'
res.srcDirs = ['src/staging/res']
}
}
buildTypes {
debug {
signingConfig signingConfigs.debug
}
release {
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
}
apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"
dependencies {
implementation("com.facebook.react:react-android")
implementation("androidx.core:core-splashscreen:1.0.0")
implementation 'com.facebook.android:facebook-android-sdk:18.0.3'
implementation project(':react-native-config')
if (hermesEnabled.toBoolean()) {
implementation("com.facebook.react:hermes-android")
} else {
implementation jscFlavor
}
}
android\app\src\staging\AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:name="health.company.myapp.staging.MainApplication"
tools:replace="android:name">
<activity
android:name="health.company.myapp.MainActivity"
tools:node="remove" />
<activity
android:name="health.company.myapp.staging.MainActivity"
android:exported="false" />
<activity-alias
android:name="health.company.myapp.MainActivity"
android:targetActivity="health.company.myapp.staging.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
</application>
</manifest>
android\app\build\generated\source\buildConfig\staging\debug\health\company\myapp\BuildConfig.java
:
package health.company.myapp;
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String APPLICATION_ID = "health.company.myapp.staging";
public static final String BUILD_TYPE = "debug";
// Field from product flavor: staging
public static final String FLAVOR = "staging";
public static final int VERSION_CODE = 100001;
public static final String VERSION_NAME = "100001.0.1-staging";
// Field from product flavor: staging
public static final String AMPLITUDE_API_KEY = "abc123";
// Field from product flavor: staging
public static final String APP_ENV = "staging";
// Field from default config.
public static final boolean IS_HERMES_ENABLED = true;
// Field from default config.
public static final boolean IS_NEW_ARCHITECTURE_ENABLED = false;
}
android\app\build\generated\source\buildConfig\production\debug\health\company\myapp\BuildConfig.java
package health.company.myapp;
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String APPLICATION_ID = "health.company.myapp";
public static final String BUILD_TYPE = "debug";
// Field from default config.
public static final String FLAVOR = "production";
public static final int VERSION_CODE = 1;
public static final String VERSION_NAME = "0.0.1";
// Field from default config.
public static final String AMPLITUDE_API_KEY = "abc123";
// Field from default config.
public static final String APP_ENV = "production";
// Field from default config.
public static final boolean IS_HERMES_ENABLED = true;
// Field from default config.
public static final boolean IS_NEW_ARCHITECTURE_ENABLED = false;
}
There default MainActivity.kt
and MainApplication.kt
in android\app\src\main\java\health\company\myapp\
and these two with diffent content in android\app\src\staging\java\health\company\myapp\staging\
I could provide all of these if needed.