Better way of using a few different resources files per build flavor
android, gradle
Solution
This is overkill.
all you need is:
src/main/res
This is your common resources for all your flavors
src/dev/res
This is the resources specific to the `dev` flavor.
src/prod/res
This is the resources specific to the `prod` flavor.
etc...
Note: if you have a resource both in `src/main/res` and `src/<flavor>/res`, the one in the flavor res folder will win.
Each flavor will actually get the combined resources of its own res folder and the one in `src/main/res`
There's no need to manually copy things, it's all done for you. One of the advantages also is that the copying/merging of the resource folders will be done incrementally which will be faster and more efficient.
It seems you are using `res` instead of `src/main/res` so maybe you are using the old legacy folder structure. This is not a problem, you can keep remapping the folders, but only specify one of them:
android {
sourceSets {
main {
res.srcDirs = ['res']
}
dev {
res.srcDirs = ['res-dev']
}
prod {
res.srcDirs = ['res-prod']
}
etc...
}
}
Note sure what is going with your 'test' flavor. Is it really a different flavor for your build or is it your test apk?
Edit: For your resource merging issue: it's not a merge. A merge is between different sourceSets. So `src/main/raw/foo.prop` gets overridden by `src/debug/raw/foo.prop`. However, in your case, think, you have the same resources in 2 source folders that are set on the same sourcesets. This is because you set on each sourceSets both the common res folder and the flavor specific res.
When you let the merger do its thing, there's a clear overriding order. Flavors override main source sets and build types override flavors.
When you have two res folders associated with the same flavor, we cannot know which one to choose.
Problem
I am trying to build an Android project which has 6 build flavors. Each has just 1 resource file that is unique to it. The Ant build copies the file from res/configs/ to res/raw/ for each flavor. I did not want to break that build and I could not figure out how to get the Gradle Android build to work with this folder structure. So I added a copy phase to get a common resource folder and then one for each flavor with just that 1 file. ``` task cleanExtra(type: Delete) { delete 'res-common' delete 'res-dev' delete 'res-qa' delete 'res-sb' delete 'res-test' delete 'res-stage' delete 'res-prod' } task setUpSharedResources(type: Copy) { from 'res' into 'res-common' exclude '**/environment.properties' } task setUpDevResources(type: Copy ) { from 'configs/dev/' into 'res-dev/raw/' } task setUpQaResources(type: Copy ) { from 'configs/qa/' into 'res-qa/raw/' } task setUpSbResources(type: Copy ) { from 'configs/sb/' into 'res-sb/raw/' } task setUpTestResources(type: Copy ) { from 'configs/test/' into 'res-test/raw/' } task setUpStageResources(type: Copy ) { from 'configs/stage/' into 'res-stage/raw/' } task setUpProdResources(type: Copy ) { from 'configs/prod/' into 'res-prod/raw/' } ``` Then set up the flavor copy tasks to run before preBuild ``` preBuild.dependsOn setUpDevResources preBuild.dependsOn setUpQaResources preBuild.dependsOn setUpSbResources preBuild.dependsOn setUpTestResources preBuild.dependsOn setUpStageResources preBuild.dependsOn setUpProdResources ``` Then the common copy tasks depend on the flavor ones so it happens first ``` setUpDevResources.dependsOn setUpSharedResources setUpQaResources.dependsOn setUpSharedResources setUpSbResources.dependsOn setUpSharedResources setUpTestResources.dependsOn setUpSharedResources setUpStageResources.dependsOn setUpSharedResources setUpProdResources.dependsOn setUpSharedResources clean.dependsOn(cleanExtra) ``` With these new res folders created I can set up my android source sets and product flavors like so ``` productFlavors { dev {} prod {} qa {} sb {} stage{} // test {} } sourceSets { main { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = ['.apt_generated','src'] resources.srcDirs = ['.apt_generated','src'] aidl.srcDirs = ['.apt_generated','src'] renderscript.srcDirs = ['.apt_generated','src'] assets.srcDirs = ['assets'] } dev { res.srcDirs = ['res-common','res-dev'] } prod { res.srcDirs = ['res-common','res-prod'] } qa { res.srcDirs = ['res-common','res-qa'] } sb { res.srcDirs = ['res-common','res-sb'] } stage { res.srcDirs = ['res-common','res-stage'] } test { res.srcDirs = ['res-common','res-test'] } debug.setRoot('build-types/debug') release.setRoot('build-types/release') } ``` Although this seems to work, its got some problems. The copy tasks are not tied to the flavors well. I just hard code the folder names. It seems like there should be some way of doing that with a loop. Or even better not doing the copy task at all and just telling Gradle which files to use neatly. Another thing I am not sure about. I did not create a test flavor because gradle complained that that one already existed. Im not sure if there is a problem with just hijacking it for a different purpose. I get the impression that I am forcing Gradle to build all the resources for all 6 flavors. Is there a way to solve this problem cleaner or faster is my question? * Follow Up * I am realizing that I could avoid the copy phase with proper resource merging. I had some problems with that which is why I did the file copy stuff. When I have the file in both of the resource folders I get this error ``` /Users/mkluver/Documents/OH-android/oep/res/raw/environment_override.properties: Error: Duplicate resources: /Users/mkluver/Documents/OH-android/oep/res/raw/environment_override.properties:raw/environment_override, /Users/mkluver/Documents/OH-android/oep/res-dev/raw/environment_override.properties:raw/environment_override ``` I am guessing the resource merging failed because these are not XML resources but properties files. formatted with lines like. ``` #This is a comment server.url=http://www.theserver.com/api server.version=5.4 ``` How can I tell gradle how to merge these sorts of files?