【问题标题】:How to use multiple res.srcDirs and override some resources with gradle如何使用多个 res.srcDirs 并用 gradle 覆盖一些资源
【发布时间】:2015-10-09 16:49:40
【问题描述】:

我想基于不同的productFlavors 构建我的应用的不同版本,但需要一定程度的灵活性,而我目前还无法实现。

这是我的文件夹结构:

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

通用代码位于 ma​​in(服务)上,而基本 ui 位于 base(活动)上。然后在 custom1 (新活动)上定义了一个定义新 ui 的应用程序的自定义版本。这运行良好。但我需要另一个版本的应用程序 (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

因为app_namebasecustom2 上都定义了,但我的目标是用base 覆盖资源的定义custom2 的那些。

我知道 app_name 将在 ma​​in 中被覆盖,如果我没有在 res.srcDirs 中为 custom2 指定任何内容,那么所有来自 的资源>base 将不可用。

方法正确吗?还是我滥用了 Gradle 提供的灵活性?还是有办法做我想做的事?

提前致谢!

【问题讨论】:

    标签: android android-studio gradle build.gradle android-productflavors


    【解决方案1】:

    你无法通过这种方式实现它。

    资源合并有优先级:

    合并的资源来自 3 类来源:

    • 主资源,与主sourceSet关联,一般位于src/main/res
    • 变体叠加层,来自构建类型和风味。
    • Library Project 依赖项,通过其 aar 包中的 res 条目贡献资源。

    here所述

    如上所述,每个 sourceSet 可以定义多个资源文件夹。例如:

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

    在这种情况下,两个资源文件夹具有相同的优先级。这意味着如果在两个文件夹中都声明了一个资源,合并将失败并报告错误

    您的情况也是如此。您不能以这种方式复制相同的资源。

    【讨论】:

    • 感谢您的评论。我以前读过那个链接,但错过了最后一段。但是,这意味着我不能做我想做的事吗?或者也许另一种方法可以解决我的情况?
    • 老实说,根据我的经验,你不能这样做。您可以在 buid.gradle 中使用 buildConfigField 和 resValue 设置图标和资源
    • 经过大量测试,恐怕得出这样的结论是做不到的。我认为可以通过排除我想要覆盖的资源来实现,但是 res.exclude 还不支持(java.exclude 也不支持)。所以这是一个等待并找到一个肮脏的解决方法的问题......无论如何,谢谢你的cmets。
    • 我事先不知道。我正在计划将来(迟早)会出现的案件。我们开发了一个供各种操作员使用的应用程序,每个操作员都想要自己的外观和感觉,从一组全新的活动到简单的图标和/或颜色更改。因此需要这种程度的灵活性。
    • 答案中的链接已损坏。截至今天的工作链接 - developer.android.com/studio/write/add-resources
    【解决方案2】:

    我能够通过在 src 的同级文件夹中添加另一个级别的文件夹(称为 shared)来实现类似的效果,然后在附加脚本中手动检查 + 组装必要的资源以避免重复。

    脚本在这里可用:https://github.com/smbgood/examples/blob/master/family-resources.gradle

    资源将进入这样的文件夹(我们有 3 个应用“家庭”,IG、JB + CB):
    /shared/JB/res/values/ids.xml

    对于我们现在拥有的每个构建变体,ids.xml 'family' 中都有一个属性来确定要使用的应用程序系列。构建时,脚本会检查 shared 中的 drawables 和 xml 文件,将它们与变体中存在的文件进行比较,然后删除重叠的项目,最后将所需的项目写入 /assembled/ 文件夹。

    【讨论】:

    • 如果您可以与示例项目共享解决方案,那将是很大的帮助。我很想实施这个解决方案。谢谢!
    【解决方案3】:

    可以设置一个覆盖res文件的路径,custom2/res中没有基础res文件。

    custom2.res.srcDir=['src/custom2/res']

    会先搜索 src/custom2/res 路径,如果文件不存在,会在编译时自动查找 src/main/res。

    【讨论】:

    猜你喜欢
    • 2014-02-05
    • 1970-01-01
    • 2022-01-28
    • 1970-01-01
    • 1970-01-01
    • 2012-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多