Inject compile-time properties with build.gradle (without modifying it)

Viewed 196

We have this in an android project I'm working on:

android {
    ...
    productFlavors {
       dev {
           buildConfigField "String", "BASE_URL", "\"https://somedevurl.com\""
       }
       prod {
           buildConfigField "String", "BASE_URL", "\"https://someprodurl.com\""
       }
    }
}

This is a simple approach and it works very well but I'd like to be able to inject keys/secret at compile time (I don't want those committed into my build.gradle for security reasons). My approach so far is to inject a strings.xml file at compile time and use to access this secret from AndroidManifest.xml, my problems with this are that we need to be careful of not committing this file / having this file referenced in .gitignore, and it feels like a hack

As an alternative to that, I made the following:

android {
    productFlavors {
        dev {
            Properties flavorProps = new Properties()
            flavorProps.load(project.rootProject.file("./app/config/dev.properties").newDataInputStream())
            flavorProps.each { p ->
                def resValuePrefix = "RES_VALUE_"
                if (p.key.startsWith(resValuePrefix)) {
                    resValue "string", p.key.substring(resValuePrefix.length()), "\"${p.value}\""
                }
                def buildConfigPrefix = "BUILD_CONFIG_"
                if (p.key.startsWith(buildConfigPrefix)) {
                    buildConfigField "String", p.key.substring(buildConfigPrefix.length()), "\"${p.value}\""
                }
            }
        }
        prod {
            Properties flavorProps = new Properties()
            flavorProps.load(project.rootProject.file("./app/config/prod.properties").newDataInputStream())
            flavorProps.each { p ->
                def resValuePrefix = "RES_VALUE_"
                if (p.key.startsWith(resValuePrefix)) {
                    resValue "String", p.key.substring(resValuePrefix.length()), "\"${p.value}\""
                }
                def buildConfigPrefix = "BUILD_CONFIG_"
                if (p.key.startsWith(buildConfigPrefix)) {
                    buildConfigField "String", p.key.substring(buildConfigPrefix.length()), "\"${p.value}\""
                }
            }
        }
    }
}

So basically I create a file per flavor under app/config/, I read every property and if the property starts with BUILD_CONFIG_ I import this property as buildConfigField, and if it starts with RES_VALUE_ I import that property as resValue.

This approach satisfies me (Now I can add compile time properties by modifying only the *.properties file) but the code is copypasted for each flavor.

My questions are:

Do you know of a better way to do this?

If not, is there a way to extract this code in order to reduce code duplication?

0 Answers
Related