I have been struggling with the same problem. At first I used two branches in my source control, but that was a head ache keeping them in sync. Gradle is a very flexible build system, but the default conventions are not always enough. Here is how I finally resolved it in my code base.
I ended up with essentially the following directory structure (simplified):
+ src
+ main
| + res
| | + values
| | - strings.xml
| + java
| ...
+ debug
| + free
| | + res
| | + values
| | - strings.xml
| + paid
| + res
| + values
| - strings.xml
+ free
| + res
| | + values
| | - strings.xml
| + java
| ...
+ paid
+ res
| + values
| - strings.xml
+ java
...
In the main folder I keep everything that is common for both flavors. In the free folder I keep everything that is unique for the free version (same for paid). The files in the flavor folder will be overlaid on top of main.
The default overlay rules will handle the product flavors "free" and "paid" by using the folders under "src" with the same names. The problem for me started starts with the overlay of build types.
If I created a debug folder with the same structure as the flavor folders it would be overlaid on top of the currently used flavor folder. That led to the same debug-name for both flavors, but I wanted different debug names depending on flavor. After some research I came up with the following modification to my build file.
...
android {
buildTypes {
debug {
...
}
release {
...
}
}
productFlavors {
free {}
paid {}
}
}
android.applicationVariants.all { variant ->
if (variant.buildType.name == "release") {
...
}
else if (variant.buildType.name == "debug") {
switch (variant.name) {
case "FreeDebug":
variant.mergeResources.doFirst {
android.sourceSets.debug.setRoot("src/debug/free")
}
break;
case "PaidDebug":
variant.mergeResources.doFirst {
android.sourceSets.debug.setRoot("src/debug/paid")
}
break;
}
}
}
...
Now the build variant will be built by first overlaying the following folders:
PaidRelease -> /src/main + /src/paid
PaidDebug -> /src/main + /src/paid + /src/debug/paid
FreeRelease -> /src/main + /src/free
FreeDebug -> /src/main + /src/free + /src/debug/free