Gradle : how to use BuildConfig in an android-library with a flag that gets set in an app

As a workaround, you can use this method, which uses reflection to get the field value from the app (not the library):

/**
 * Gets a field from the project's BuildConfig. This is useful when, for example, flavors
 * are used at the project level to set custom fields.
 * @param context       Used to find the correct file
 * @param fieldName     The name of the field-to-access
 * @return              The value of the field, or {@code null} if the field is not found.
 */
public static Object getBuildConfigValue(Context context, String fieldName) {
    try {
        Class<?> clazz = Class.forName(context.getPackageName() + ".BuildConfig");
        Field field = clazz.getField(fieldName);
        return field.get(null);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    return null;
}

To get the DEBUG field, for example, just call this from your Activity:

boolean debug = (Boolean) getBuildConfigValue(this, "DEBUG");

I have also shared this solution on the AOSP Issue Tracker.


Update: With newer versions of the Android Gradle plugin publishNonDefault is deprecated and has no effect anymore. All variants are now published.

The following solution/workaround works for me. It was posted by some guy in the google issue tracker:

Try setting publishNonDefault to true in the library project:

android {
    ...
    publishNonDefault true
    ...
}

And add the following dependencies to the app project that is using the library:

dependencies {
    releaseCompile project(path: ':library', configuration: 'release')
    debugCompile project(path: ':library', configuration: 'debug')
}

This way, the project that uses the library includes the correct build type of the library.


You can't do what you want, because BuildConfig.SOME_FLAG isn't going to get propagated properly to your library; build types themselves aren't propagated to libraries -- they're always built as RELEASE. This is bug https://code.google.com/p/android/issues/detail?id=52962

To work around it: if you have control over all of the library modules, you could make sure that all the code touched by callToBigLibraries() is in classes and packages that you can cleave off cleanly with ProGuard, then use reflection so that you can access them if they exist and degrade gracefully if they don't. You're essentially doing the same thing, but you're making the check at runtime instead of compile time, and it's a little harder.

Let me know if you're having trouble figuring out how to do this; I could provide a sample if you need it.