我想基于不同的 productFlavors 构建我的应用程序的不同版本,但需要一定程度的灵活性,这是我无法实现的。
这是我的文件夹结构:
+src
+main
+java
+res
+base
+java
+res
+custom1
+java
+res
+custom2
+res
公共代码位于 main (服务),基础ui位于 base (活动)。然后,定义新UI的应用程序的自定义版本位于 custom1 (新活动)上。这个运行正常。但我需要另一个版本的应用程序( custom2 ),它使用 base ui,但更改了一些res(图标,字符串或颜色)。
我在build.gradle文件中尝试的是:
android{
...
productFlavors {
base {
...
}
custom1 {
...
}
custom2 {
...
}
}
sourceSets{
custom2{
java.srcDirs = ['src/base/java']
res.srcDirs = ['src/custom2/res', 'src/base/res']
}
}
}
指定 custom2 将使用 base 的源代码和资源以及 custom2 的资源。
问题是我得到了:
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
因为基础和 custom2 都定义了app_name
,但我的目标是覆盖 base 使用 custom2 。
我知道如果我没有在app_name
中为 custom2 指定任何内容,res.srcDirs
将在主中覆盖,但随后全部 base 中的资源将无法使用。
方法是否正确?或者我滥用Gradle提供的灵活性?或者有办法做我想做的事情?
提前致谢!
答案 0 :(得分:6)
你无法以这种方式实现它。
资源合并有一个优先事项:
合并的资源来自3种类型的来源:
如上所述here
如上所述,每个sourceSet都可以定义多个资源文件夹。例如:
android.sourceSets {
main.res.srcDirs = ['src/main/res', 'src/main/res2']
}
在这种情况下,两个资源文件夹都具有相同的优先级。这意味着如果在两个文件夹中声明资源,合并将失败并报告错误。
在你的情况下也是如此。您不能以这种方式复制相同的资源。
答案 1 :(得分:1)
我能够通过在src的sibling中添加另一级文件夹(称为shared)来实现这样的功能,然后手动检查+在另一个脚本中组装必要的资源以避免重复。
脚本可在此处找到:https://github.com/smbgood/examples/blob/master/family-resources.gradle
资源将进入这样的文件夹(我们有3个应用'家庭',IG,JB + CB):
/shared/JB/res/values/ids.xml
对于我们现在拥有的每个构建变体,ids.xml“family”中都有一个属性,用于确定要使用的应用程序系列。构建时,脚本会检查在共享中找到的drawable和xml文件,将它们与变体中存在的文件进行比较,然后删除重叠的项目,最后将所需的项目写入/ assemble /文件夹。