How to use multiple res.srcDirs and override some resources with gradle

I want to create different versions of my application based on different products, but you need a certain degree of flexibility that I can’t reach yet.

This is my folder structure:

+src +main +java +res +base +java +res +custom1 +java +res +custom2 +res 

The common code is on the main (service), and the ui base is on the basis (activity). Then the user version of the application defining the new ui is on custom1 (new activity). This is working fine. But I need another version of the application ( custom2 ) that uses base ui, but changes some parameters (icons, lines or colors).

What I'm trying in the build.gradle file:

 android{ ... productFlavors { base { ... } custom1 { ... } custom2 { ... } } sourceSets{ custom2{ java.srcDirs = ['src/base/java'] res.srcDirs = ['src/custom2/res', 'src/base/res'] } } } 

To indicate that custom2 will use the source code and base resources and custom2 resources.

The problem is that I get a:

 Error: Duplicate resources: <project_path>/src/base/res/values-es/strings.xml:string-en/app_name, <project_path>/src/custom2/res/values-es/strings.xml:string-en/app_name 

Since app_name defined both on the base and on custom2 , but my goal is to override the definition of resources in the database using <those custom2 .

I know that app_name will be overridden in main if I don't specify anything in res.srcDirs for custom2 , but then all resources from base will be unavailable.

Is the approach right? or am I abusing the flexibility that Gradle offers? or is there a way to do what I'm trying to do?

Thanks in advance!

+7
android android-studio build.gradle gradle android-productflavors
source share
2 answers

You cannot achieve this in this way.

Merging resources has priority:

Pooled resources come from three types of sources:

  • The main resources associated with the main source are usually located in src / main / res
  • An overlay option based on build type and taste.
  • Library project dependencies that contribute resources through a res entry in their aar package.

As described here

As mentioned above, each sourceSet can define multiple resource folders. For example:

 android.sourceSets { main.res.srcDirs = ['src/main/res', src/main/res2'] 

}

In this case, both resource folders have the same priority. This means that if a resource is declared in both folders, the merge will fail and an error message will be generated .

The same thing happens in your case. Therefore, you cannot duplicate the same resources.

+3
source share

I was able to achieve something similar by adding another level of folders to sibling src called shared, and then manually checking + collecting the necessary resources in an additional script to avoid duplication.

The script can be found here: https://github.com/smbgood/examples/blob/master/family-resources.gradle

Resources will be included in such folders (we have 3 application families, IG, JB + CB):
/shared/JB/res/values/ids.xml

For each build option, we have a property in ids.xml 'family', which determines which application family to use. When building the script, it checks the drawings and xml files found in shared, compares them with those that are present in this option, and then removes the overlapping elements and, finally, writes the necessary elements to the / assembly / folder.

+1
source share

All Articles