I would like to convert CommonsWare's comment to an answer. I'll then explain how the final directory setup should look like. I hope this helps out the people stumbling upon this question through search.
Well, you can override resources in flavors. So, have the common one
in main/res/layout/
and the flavor-specific one in
yourFlavorHere/res/layout/
.
So, if the Customization
activity's layout file is called activity_customization.xml
, you'll leave its common copy shared among the three flavors under src/main/res/layout
directory and place the modified layout xml to be used by, say flavorFour
, under its corresponding source set directory src/flavorFour/res/layout
.
The way this works is that since flavor one to three (unlike flavor four) haven't provided their own versions of activity_customization.xml
, they'll inherit the one coming from the main
source set.
It's the activity Java class that gets tricky. Another possibility for
that is to configure the flavors with the same activity implementation
to pull from two source directories: a flavor-specific one and a
common one with the common class implementation.
Unlike resources, Java code files are not merged or overridden. So, you can't have Java files with the same fully qualified class name under main
as well as in any of your flavor source sets. If you do, you'll receive a duplicate class error.
To resolve this issue, the simplest solution is to move Customization
activity out of the main
and into each flavor source set. This works because the flavor directories are mutually exclusive (with each other, not with main
) hence avoiding the conflict.
But this means three out of the four flavors have a duplicate copy of the activity - a maintenance nightmare - just because one of the flavors required some changes to it. To resolve this issue we can introduce another source directory that keeps just the common code files shared between the three flavors.
So, the build.gradle
script would look something like
android {
...
productFlavors {
flavorOne {
...
}
flavorTwo {
...
}
flavorThree {
...
}
flavorFour {
...
}
}
sourceSets {
flavorOne.java.srcDir 'src/common/java'
flavorTwo.java.srcDir 'src/common/java'
flavorThree.java.srcDir 'src/common/java'
}
}
Notice the use of java.srcDir
(and not srcDirs
) which adds another Java source directory to the already existing default src/flavorX/java
.
Now all we need to do is to drop the common Customization
activity file in src/common/java
to make it available to the flavors one to three. The modified version required by flavorFour
would go under its own source set at src/flavorFour/java
.
So, the final project structure would look something like
+ App // module
|- src
|- common // shared srcDir
|- java
|- path/to/pkg
|- CustomizationActivity.java // inherited by flavors 1, 2, 3
+ flavorOne
+ flavorTwo
+ flavorThree
+ flavorFour
|- java
|- path/to/pkg
|- CustomizationActivity.java // per-flavor activity class
|- res
|- layout
|- activity_customization.xml // overrides src/main/res/layout
|- main
+ java
|- res
|- layout
|- activity_customization.xml // inherited by flavors 1, 2, 3