lugg / react-native-config

Bring some 12 factor love to your mobile apps!
MIT License
4.81k stars 658 forks source link

[Android] Empty Config Object #400

Open Jashtezakonshem opened 5 years ago

Jashtezakonshem commented 5 years ago

Hi guys, I'm stuck when it comes to make it work Android. iOS is working smoothly but when it comes to use Config.API_URL, Config is an empty object when working on JS side. I'm using

"react-native": "0.60.4","react-native-config": "^0.11.7"

I'm also using react-native-navigation 3.0

In my app/build.gradle I added apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle" this is my defaultConfig (I added the row required in advanced android setup) image

this is my androidManifest.xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.wroomapp">.

The weird part is that I can see native android properly initialized, since BuildConfig.java shows correctly envs.

image

Am I missing something? Any workaround to deal with the problem?

Thank you

drbarto commented 5 years ago

Same issue with react-native 0.61.2 and react-native-config 0.11.7. The env lookup used to work with a pre-0.60 react-native, since upgrading to 0.61 it's broken on Android (but still works on iOS).

shubhamdeol commented 4 years ago

same here. for me this works for debug apk. when I am creating production release apk. I am also receiving undefined values from env file.

smakosh commented 4 years ago

Having the same issue, getting an empty object with react-native: 0.61.2 and I'm using this repository and not the one on npm.

smakosh commented 4 years ago

I had to use the previous commit and it worked fine.

VadimZP commented 4 years ago

Same. I'm using react-native: 0.61.2, react-native-config: 0.11.7,

humqn commented 4 years ago

Hello, don't forget to add -keep class host.exp.exponent.BuildConfig { *; } in your android/app/proguard-rules.pro for release build (depending on your configuration but proguard might be only enabled for your release build) This is why it works only on your debug version.

helderberto commented 4 years ago

These steps below worked to me:

Package versions:

"react": "16.9.0",
"react-native": "0.61.2",
"react-native-config": "luggit/react-native-config#1eb6ac01991210ddad2989857359a0f6ee35d734"

android/app/build.gradle

Add this line:

apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"

In my case, using multiple flavors need to add:

defaultConfig {
    resValue "string", "build_config_package", "PACKAGE_NAME_IN_ANDROID_MANIFEST.XML"
   ...
}

After, I created a simple script in the package.json:

"run:android:dev": "ENVFILE=.env.dev react-native run-android --variant=devDebug",
"run:android:staging": "ENVFILE=.env.staging react-native run-android --variant=stagingDebug",
"run:android:prod": "ENVFILE=.env.production react-native run-android --variant=prodDebug",
"build:android:prod": "npx jetify && cd android && ENVFILE=.env.production ./gradlew assembleprodRelease",
"build:android:dev": "npx jetify && cd android && ENVFILE=.env.dev ./gradlew assembledevRelease",
"build:android:staging": "npx jetify && cd android && ENVFILE=.env.staging ./gradlew assemblestagingRelease",

Add to MainApplication.java:

import com.lugg.ReactNativeConfig.ReactNativeConfigPackage;

@Override
protected List<ReactPackage> getPackages() {
      @SuppressWarnings("UnnecessaryLocalVariable")
      List<ReactPackage> packages = new PackageList(this).getPackages();
      // Packages that cannot be autolinked yet can be added manually here, for example:
      // packages.add(new MyReactNativePackage());

      new ReactNativeConfigPackage();

      return packages;
}

My product flavors are configured like below:

flavorDimensions "default"
    productFlavors {
        prod {
            versionName "0.1.0"
            versionNameSuffix "-prod"
        }
        staging {
            versionName "0.1.0"
            applicationIdSuffix ".staging"
            versionNameSuffix "-staging"
        }
        dev {
            versionName "0.1.0"
            applicationIdSuffix ".dev"
            versionNameSuffix "-dev"
        }
    }
strdr4605 commented 4 years ago

@helderburato I had this error when building flavors

defaultConfig {
    resValue "string", "build_config_package", "com.example"
   ...
}

worked for me

helderberto commented 4 years ago

could you share your react-native-config version from your package.json? @strdr4605

strdr4605 commented 4 years ago

@helderburato, "react-native-config": "0.11.7",

helderberto commented 4 years ago

I tried here with version "react-native-config": "0.11.7" but really doesn't work. I need to use this specific commit version "react-native-config": "luggit/react-native-config#1eb6ac01991210ddad2989857359a0f6ee35d734" @strdr4605

When I use version 0.11.7 I get this error #187.

MASAKASUNO1 commented 4 years ago

I having the same issue, getting an empty object only android-release-build situation.

I tried above fixes, hovever, it doesnt work.

***my environment***
    "react-native": "0.60.5",
    "react-native-config": "0.12.0",
ribbedcrown commented 4 years ago

@MASAKASUNO1 Double check your Proguard rule, stupidly copy-pasting from doc was my mistake)

-keep class com.mypackage.BuildConfig { *; }

Currently it works as expected on Android for me. My package versions:

    "react-native": "0.61.5",
    "react-native-config": "0.12.0",
shubhamdeol commented 4 years ago

@MASAKASUNO1 have you found any solution for this?

shubhamdeol commented 4 years ago

I had to use the previous commit and it worked fine.

@smakosh which commit worked for you?

smakosh commented 4 years ago

I had to use the previous commit and it worked fine.

@smakosh which commit worked for you?

git+ssh://git@github.com:luggit/react-native-config#1eb6ac0

mengheangrat commented 4 years ago

It worked when I added

defaultConfig {
        ....
        // react-native-config
        resValue "string", "build_config_package", "mypackage"
    }

In app/build.gradle

MrRob0t404 commented 4 years ago

Tried the above ^ does not work

MrRob0t404 commented 4 years ago

Has anyone resolved this issue yet?

SachArora commented 4 years ago

I resolved this issue by adding -keep class <package_name>.BuildConfig { *; } in proguard-rules.pro. Please don't forget to change your package name before paste this in proguard-rules.pro file.

igorrfc commented 4 years ago

It worked when I added

defaultConfig {
        ....
        // react-native-config
        resValue "string", "build_config_package", "mypackage"
    }

In app/build.gradle

@mengheangrat's solution worked for me. I just needed to add the com. before my "packagename"

margaridaDinis commented 4 years ago

I was having the same issue with

"react-native": "0.61.2",
"react-native-config": "^0.12.0",
"react-native-navigation": "^4.6.0",

React-native-navigation is the reason why Config was empty. This fixed for me: https://github.com/luggit/react-native-config/issues/243#issuecomment-379349157

FYI I have other apps where I don't use react-native-navigation and didn't have this issue

swain commented 4 years ago

Still having this issue, using React Native 0.61.5 and react-native-config 0.12.0.

Things I've triple-checked:

I AM seeing the environment variables I've defined appear in the BuildConfig class on build. But, they aren't exposed to the JS (just getting an empty config object there.

Thanks so much for any help!

genesisxyz commented 4 years ago

I fixed the problem by reading the README again, on android/app/build.gradle:

// 2nd line, add a new apply: apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"

Placing that exactly as the second line after

apply plugin: "com.android.application"

solved the problem, works for me with both proguard and R8 enabled, I am using React Native 0.61.4 with react-native-config from this commit 1eb6ac01991210ddad2989857359a0f6ee35d734

cristiancedenogallego commented 4 years ago

This works for me react-native unlink react-native-config react-native link react-native-config

YahiaJabeur commented 4 years ago

I m still facing the problem on android ...

  1. I added "react-native-config": "luggit/react-native-config#1eb6ac01991210ddad2989857359a0f6ee35d734",
  2. I added apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle" in the 2nd line , just after apply plugin: "com.android.application"
  3. I added resValue "string", "build_config_package", "YOUR_PACKAGE_NAME_IN_ANDROIDMANIFEST.XML" to defaultConfig in AndroidManifest.xml
  4. I added new ReactNativeConfigPackage() is in MainApplication.java file.
  5. I added -keep class com..BuildConfig { *; } in proguard-rules.pro I m using "react-native": "0.61.4" in the android project i use different buildTypes and flavors

It only works when I add: defaultEnvFile = ".env.prod" to buildscript.ext {} but the problem of this solution that it always read from env.prod by defaults

can anyone help please ?

Natteke commented 4 years ago

If you faced this on ios try to put pre-action script in your scheme.

goto -> product -> scheme -> edit scheme, and...

image

echo ".env" > /tmp/envfile

Lifehack: For multiple .env files i suggest you to make multiple schemes by duplicating and renaming the original one.

like this: image image image

put there different pre-script and just chose which you want to build

YahiaJabeur commented 4 years ago

I m facing a prob on android It works when I use the command cd android && ENVFILE=.env.dev ./gradlew assembledevRelease But it don't works when using the command: ENVFILE=.env.dev react-native run-android --variant=devDebug I receive this error


* Missing .env file **


any idea whats s the differance and why it dont works ??????????

majidmvulle commented 4 years ago

@helderburato How is this working for you? I have done these exact steps, it just doesn't work on Android.

    "react": "^16.11.0",
    "react-hook-form": "^4.10.1",
    "react-moment": "^0.9.7",
    "react-native": "0.61.3",
    "react-native-config": "luggit/react-native-config#1eb6ac01991210ddad2989857359a0f6ee35d734",
chenop commented 4 years ago

Note that "PACKAGE_NAME_IN_ANDROID_MANIFEST.XML" means: [Package name in AndroidManifest.xml] not [package name in AndroidManifest].xml

defaultConfig {
    resValue "string", "build_config_package", "com.packageName" // No .xml extension!
   ...
}

Yes I fell for it...

yunussaha commented 4 years ago

Note that "PACKAGE_NAME_IN_ANDROID_MANIFEST.XML" means: [Package name in AndroidManifest.xml] not [package name in AndroidManifest].xml

defaultConfig {
    resValue "string", "build_config_package", "com.packageName" // No .xml extension!
   ...
}

Yes I felt for it...

Docs should be changed to reflect this. remove .xml from PACKAGE_NAME_IN_ANDROID_MANIFEST.XML

mwagena commented 4 years ago

-keep class com.app.name.BuildConfig { *; } was the fix for me!

jmusakka commented 4 years ago

I managed to make it work on

react-native 0.61.5
react-native-config 0.12.0

In the beginning of app/build.gradle I have:

apply plugin: "com.android.application"

// these are the flavors
project.ext.envConfigFiles = [
    local: ".env.local",
    sandbox: ".env.sandbox",
    production: ".env.production"
]

// this needs to come AFTER the project.ext.envConfigFiles initialization
apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"

def ENVCONFIG = { k -> "\"${project.env.get(k)}\"" }

...

Then, the env file was found, but CONFIG object was empty in RN. Adding the following to proguard-rules.pro fixed it.

NOTE: remember to change com.example.xyz --> your own app ID.

-keep class com.example.xyz.BuildConfig { *; }

zabojad commented 4 years ago

Should we adapt the proguard-rules.pro when using applicationIdSuffix in app's build.graddle ?

alexandergiraldo commented 4 years ago

Hey @Jashtezakonshem Did you find a way to fix this issue?

SpQuyt commented 3 years ago

These steps below worked to me:

Package versions:

"react": "16.9.0",
"react-native": "0.61.2",
"react-native-config": "luggit/react-native-config#1eb6ac01991210ddad2989857359a0f6ee35d734"

android/app/build.gradle

Add this line:

apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"

In my case, using multiple flavors need to add:

defaultConfig {
    resValue "string", "build_config_package", "PACKAGE_NAME_IN_ANDROID_MANIFEST.XML"
   ...
}

After, I created a simple script in the package.json:

"run:android:dev": "ENVFILE=.env.dev react-native run-android --variant=devDebug",
"run:android:staging": "ENVFILE=.env.staging react-native run-android --variant=stagingDebug",
"run:android:prod": "ENVFILE=.env.production react-native run-android --variant=prodDebug",
"build:android:prod": "npx jetify && cd android && ENVFILE=.env.production ./gradlew assembleprodRelease",
"build:android:dev": "npx jetify && cd android && ENVFILE=.env.dev ./gradlew assembledevRelease",
"build:android:staging": "npx jetify && cd android && ENVFILE=.env.staging ./gradlew assemblestagingRelease",

Add to MainApplication.java:

import com.lugg.ReactNativeConfig.ReactNativeConfigPackage;

@Override
protected List<ReactPackage> getPackages() {
      @SuppressWarnings("UnnecessaryLocalVariable")
      List<ReactPackage> packages = new PackageList(this).getPackages();
      // Packages that cannot be autolinked yet can be added manually here, for example:
      // packages.add(new MyReactNativePackage());

      new ReactNativeConfigPackage();

      return packages;
}

My product flavors are configured like below:

flavorDimensions "default"
    productFlavors {
        prod {
            versionName "0.1.0"
            versionNameSuffix "-prod"
        }
        staging {
            versionName "0.1.0"
            applicationIdSuffix ".staging"
            versionNameSuffix "-staging"
        }
        dev {
            versionName "0.1.0"
            applicationIdSuffix ".dev"
            versionNameSuffix "-dev"
        }
    }

The package commit + The flavor addition makes my config in android working. Thank you!

badkos commented 3 years ago

It worked when I added

defaultConfig {
        ....
        // react-native-config
        resValue "string", "build_config_package", "mypackage"
    }

In app/build.gradle

Save my day! Works!

DanielDanaee commented 3 years ago

@helderburato I had this error when building flavors

defaultConfig {
    resValue "string", "build_config_package", "com.example"
   ...
}

worked for me

Life saver. Thank you

designervoid commented 3 years ago

https://github.com/luggit/react-native-config#extra-step-for-android helped me

RublevD commented 3 years ago

These steps below worked to me:

Package versions:

"react": "16.9.0",
"react-native": "0.61.2",
"react-native-config": "luggit/react-native-config#1eb6ac01991210ddad2989857359a0f6ee35d734"

android/app/build.gradle

Add this line:

apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"

In my case, using multiple flavors need to add:

defaultConfig {
    resValue "string", "build_config_package", "PACKAGE_NAME_IN_ANDROID_MANIFEST.XML"
   ...
}

After, I created a simple script in the package.json:

"run:android:dev": "ENVFILE=.env.dev react-native run-android --variant=devDebug",
"run:android:staging": "ENVFILE=.env.staging react-native run-android --variant=stagingDebug",
"run:android:prod": "ENVFILE=.env.production react-native run-android --variant=prodDebug",
"build:android:prod": "npx jetify && cd android && ENVFILE=.env.production ./gradlew assembleprodRelease",
"build:android:dev": "npx jetify && cd android && ENVFILE=.env.dev ./gradlew assembledevRelease",
"build:android:staging": "npx jetify && cd android && ENVFILE=.env.staging ./gradlew assemblestagingRelease",

Add to MainApplication.java:

import com.lugg.ReactNativeConfig.ReactNativeConfigPackage;

@Override
protected List<ReactPackage> getPackages() {
      @SuppressWarnings("UnnecessaryLocalVariable")
      List<ReactPackage> packages = new PackageList(this).getPackages();
      // Packages that cannot be autolinked yet can be added manually here, for example:
      // packages.add(new MyReactNativePackage());

      new ReactNativeConfigPackage();

      return packages;
}

My product flavors are configured like below:

flavorDimensions "default"
    productFlavors {
        prod {
            versionName "0.1.0"
            versionNameSuffix "-prod"
        }
        staging {
            versionName "0.1.0"
            applicationIdSuffix ".staging"
            versionNameSuffix "-staging"
        }
        dev {
            versionName "0.1.0"
            applicationIdSuffix ".dev"
            versionNameSuffix "-dev"
        }
    }

Thank you very much! Worked for me

stanislav-sidorov-empeek commented 2 years ago

I was trying to use multiple env files, like env.prod, env.dev and always was getting undefined on android

adding this to app/build.gradle file helped me

project.ext.envConfigFiles = [
    debug: ".env.development",
    release: ".env.production"
]

apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"

for ios need to add schemas everything is written in readme file

now works well both

and my package.json to run scripts

"android": "ENVFILE=.env.development react-native run-android",
    "android:prod": "ENVFILE=.env.production react-native run-android",
    "ios": "ENVFILE=.env.development react-native run-ios --simulator 'iPhone 11 Pro' --scheme 'development'",
    "ios:prod": "ENVFILE=.env.production react-native run-ios --simulator 'iPhone 11 Pro' --scheme 'production'",
    "ios:device": "ENVFILE=.env.development react-native run-ios --device 'iPhone 6s' --scheme 'development'",
    "ios:device:prod": "ENVFILE=.env.production react-native run-ios --device 'iPhone 6s' --scheme 'production'",
    "start": "react-native start",
    "test": "jest",
    "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
    "prettier": "prettier --write \"src/**/*.{ts,tsx}\"",
    "tsc": "ENVFILE=.env.production tsc --project tsconfig.build.json",
    "clean": "rimraf build",
    "build": "yarn run clean && yarn run tsc",
    "devmenu": "adb shell input keyevent 82",
    "apk:prod": "cd android && ENVFILE=.env.production ./gradlew assembleRelease && cd ..",
    "apk:dev": "cd android && ENVFILE=.env.development ./gradlew assembleRelease && cd ..",
    "aab:prod": "cd android && ENVFILE=.env.production ./gradlew bundleRelease && cd ..",
    "aab:dev": "cd android && ENVFILE=.env.development ./gradlew bundleRelease && cd ..",
    "install:prod": "cd android && ENVFILE=.env.production ./gradlew installRelease && cd ..",
    "install:dev": "cd android && ENVFILE=.env.development ./gradlew installRelease && cd .."
praiseisaac commented 2 years ago

It my case, I had a different applicationId from the package name in AndroidManifest.xml see more info here: https://github.com/luggit/react-native-config#advanced-android-setup

pistonsky commented 2 years ago

I found the cause. Let's say your package name is com.example.app. In the source code for android, we can see:

    try {
      Context context = getReactApplicationContext();
      int resId = context.getResources().getIdentifier("build_config_package", "string", context.getPackageName());
      String className;
      try {
        className = context.getString(resId);
      } catch (Resources.NotFoundException e) {
        className = getReactApplicationContext().getApplicationContext().getPackageName();
      }
      Class clazz = Class.forName(className + ".BuildConfig");
      Field[] fields = clazz.getDeclaredFields();
      for(Field f: fields) {
        try {
          constants.put(f.getName(), f.get(null));
        }
        catch (IllegalAccessException e) {
          Log.d("ReactNative", "ReactConfig: Could not access BuildConfig field " + f.getName());
        }
      }
    }
    catch (ClassNotFoundException e) {
      Log.d("ReactNative", "ReactConfig: Could not find BuildConfig class");
    }

So this line:

Class clazz = Class.forName(className + ".BuildConfig");

where we try to access com.example.app.BuildConfig, results in ClassNotFoundException.

pistonsky commented 2 years ago

Just add

-keep class com.example.app.BuildConfig {*;}

to android/app/proguard-rules.pro. Replace com.example.app with your package name.

ClaudionorJunior commented 2 years ago

the solution below solved to me:

defaultConfig {
        ...
        resValue "string", "build_config_package", "mypackage"
}

now my Config variable is not undefined

nppull commented 1 year ago

@helderburato I had this error when building flavors

defaultConfig {
    resValue "string", "build_config_package", "com.example"
   ...
}

worked for me

you save my life

GuidoGagliardini commented 1 year ago

@helderburato I had this error when building flavors

defaultConfig {
    resValue "string", "build_config_package", "com.example"
   ...
}

worked for me

I was able to solve my problem, thanks to your help! I just have to add that instead of my packageName from my AndroidManifest.xml, I had to put the name that I had configured in my namespace, which by mistake is different from the AndroidManifest.xml. I think that's why I have the Error type 3 problem, but it's another problem to solve. Thank you so much!!

AhteshamKhanCoder commented 1 year ago

@helderberto This worked for me bundle_id will be your com.bundle.app

    defaultConfig {
    resValue "string", "build_config_package", "bundle_id"
}