是否可以在 Android Gradle 中为每个构建变体提供自定义源文件?

Is ist possible to have custom source files per build variant in Android Gradle?

我们的应用程序有免费和付费版本。我们还制作品牌版本,这意味着应用程序在两个维度上有所不同。

四个版本可能是:

  • 应用程序,耐克版。自由
  • APP,耐克版。有薪酬的
  • 该应用程序,阿迪达斯编辑。有薪酬的
  • 该应用程序,阿迪达斯编辑。自由

我现在的解决方案是有两种构建类型,付费和免费:

1
2
3
4
5
6
7
8
9
  buildTypes {
        paid {
            packageNameSuffix".paid"
        }

        free {
            packageNameSuffix".free"
        }
    }

还有两种构建风格:

1
2
3
4
5
6
7
8
9
10
productFlavors{
    nike{
        packageName"com.example.theapp.nike"
    }

    adidas{
        packageName"com.example.theapp.adidas"
    }

}

应用程序的每个免费版本都使我们成为一个内容提供者,一个内容提供者,每个风味构建类型组合都是特定的。问题是我不明白根据构建变体将源文件放在哪里。将根据构建类型或风格选择放入 /src/nike 或 /src/free 的源文件。但是依赖于构建变体(类型和风格的组合)的源文件呢?


您可以在 src 下为您拥有的每个版本或风格创建一个新文件夹。即:\\'免费\\'、\\'付费\\'、\\'nike\\'、\\'adidas\\'。

在构建时会根据类型提取您放入任何这些文件夹中的文件并同时构建两者。

根据 Android 工具项目站点上的 Gradle 插件用户指南:

Similar to Build Types, Product Flavors also contribute code and
resources through their own sourceSets.

The following rules are used when dealing with all the sourcesets used
to build a single APK:

  • All source code (src/*/java) are used together as multiple folders generating a single output.
  • Manifests are all merged together into a single manifest. This allows Product Flavors to have different components and/or
    permissions, similarly to Build Types.
  • All resources (Android res and assets) are used using overlay priority where the Build Type overrides the Product Flavor, which
    overrides the main sourceSet.
  • Each Build Variant generates its own R class (or other generated source code) from the resources. Nothing is shared between
    variants.

意味着您的 buildType "free" 的 java 文件将覆盖您的口味 "nike" 如果它们具有相同的名称。

但是,如果您要向清单添加内容,根据上面列表中的第二点,最终清单将是所有清单的合并。

如果您需要更多自定义,可以将文件放在构建变体的文件夹 "src/freeNike/" 中。


由于覆盖规则,我在构建类型覆盖口味方面遇到了类似的问题。

我最终将构建类型源集重定向到不同的文件夹,具体取决于构建的风格。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
android.applicationVariants.all { variant ->
    switch (variant.name) {
        case"FreeNike":
            variant.mergeResources.doFirst {
                android.sourceSets.free.setRoot("src/freeNike")
            }
            break;
        case"FreeAdidas":
            variant.mergeResources.doFirst {
                android.sourceSets.free.setRoot("src/freeAdidas")
            }
            break;
        case"PaidNike":
            variant.mergeResources.doFirst {
                android.sourceSets.paid.setRoot("src/paidNike")
            }
            break;
        case"PaidAdidas":
            variant.mergeResources.doFirst {
                android.sourceSets.paid.setRoot("src/paidAdidas")
            }
            break;
    }
}

您当然可以随意使用不同的文件夹结构。请参阅此处的示例:gradle build variables

的文件夹命名约定


看看最新的 Gradle 插件,它现在允许拥有变体特定资源
http://tools.android.com/tech-docs/new-build-system

这里有使用示例
https://android.googlesource.com/platform/tools/build/ /master/tests/overlay3/


您是否尝试将 srcDir 放入 sourceSets 中?
像这样:

1
2
3
4
5
6
7
    sourceSets {
            main {
                java {
                    srcDirs 'src/java'
                }
            }
     }

应该输出一个带有两个源代码的 javaResources,nike 和 adidas。