1

I'm developing a Flutter application with different product flavors for Android and want to be able to define a value for each flavor, and select the value based on which flavor I'm building, and interpolate it into a properties file in order to dynamically configure a third party library. I would also be open to having multiple duplicate properties files, each with their flavor-specific values, and then selecting the right one at build time.

My research suggests I'm likely taking the wrong approach. After reading the Android documentation, I tried using BuildConfig to generate the values and then reference them in the properties file. I do see that the BuildConfig.java is built with the right values, but they are not being interpolated in my properties file. I'm not sure what approach I should be taking here, so any suggestions would be great!

thirdPartyLibrary.properties

customProperty=${BuildConfig.CUSTOM_PROPERTY}

build.gradle

...

flavorDimensions "app"

    productFlavors {
        dev {
            dimension "app"
            buildConfigField "String", "CUSTOM_PROPERTY", "\"my custom property for dev\""
        }
        qa {
            dimension "app"
            buildConfigField "String", "CUSTOM_PROPERTY", "\"my custom property for qa\""
        }
    }
    
    ...

Daniel Allen
  • 894
  • 1
  • 10
  • 23

2 Answers2

0

I managed to get this working by following the steps outlined here: https://stackoverflow.com/a/47992042/4215892

So I removed the values from my properties file, and instead added this code to the gradle file:

...

def thirdPartyLibraryProperties = new Properties()
File thirdPartyConfig = file("src/main/assets/thirdPartyLibrary.properties")

flavorDimensions "app"

    productFlavors {
        dev {
            dimension "app"
            thirdPartyLibraryProperties.load(thirdPartyConfig.newDataInputStream())
            thirdPartyLibraryProperties.setProperty("customProperty", "my custom property for dev")
            thirdPartyLibraryProperties.store(thirdPartyConfig.newWriter(), null)
        }
        qa {
            dimension "app"
            thirdPartyLibraryProperties.load(thirdPartyConfig.newDataInputStream())
            thirdPartyLibraryProperties.setProperty("customProperty", "my custom property for qa")
            thirdPartyLibraryProperties.store(thirdPartyConfig.newWriter(), null)
        }
    }
    
    ...

However this feels like I'm repeating myself unnecessarily and like there is probably a cleaner solution. It is also modifying a file that is in source and not the build destination, which is generally bad practice.

Daniel Allen
  • 894
  • 1
  • 10
  • 23
0

The correct thing to do here was to simply create duplicate configuration files for each flavor and place the flavor-specific properties files in the correct folder for the flavor, so that it is copied to the correct "build/app/intermediates/merged_assets" folder. So instead of having a single "src/main/assets/thirdPartyLibrary.properties" file, I now have two files, one for dev and one for QA: "src/dev/assets/thirdPartyLibrary.properties" "src/qa/assets/thirdPartyLibrary.properties"

This is so painfully obvious once you understand how Android's build system works, but was initially opaque to me as a new Flutter developer.

This is the thread that pointed me at the right answer: Reference different assets based on build flavor

Daniel Allen
  • 894
  • 1
  • 10
  • 23