dynamic生成产品口味

我已经创build了一个Android应用程序,需要build立在许多(30 +)味道。

我的想法是直接从我的src目录中的文件夹结构生成不同的productFlavors ,因为configuration总是非常相似(基本上只是另一个packageName,一个新的启动器图标和一些string更改)。

src文件夹看起来像这样:

 └── src ├── flavor1 │  ├── flavor2.keystore │  ├── res ├── flavor2 │  ├── res │  ├── flavor2.keystore └── main  ├── AndroidManifest.xml  ├── java  └── res 

如果我不得不手动创buildgradle属性,它会看起来像这样:

 android { .... productFlavors { flavor1 { packageName 'com.example.flavor1' } flavor2 { packageName 'com.example.flavor2' } } } 

每次我尝试更改productFlavorsconfiguration创build后,我得到一个错误或更改/添加被默认地忽略。
这可能是我造成的问题,因为我的Gradle / Groovy经验非常有限,或者这是不可能的。

我大多得到错误,说GroupableProductFlavorDsl_Decorated不能以我想要的方式操纵。

我试图存档的内容应该是这样的:

 android { .... def flavors = getMyFlavorsFromFileSystem() productFlavors { } flavors.each { name, config -> productFlavors[name] << config } } 

注:我知道这个问题基本上是一个老问题的重复 ,可悲的是从来没有回答。 由于Gradle对Android世界是一种新鲜的东西,我希望能够从最后一次提问之后得到更多的答案,因为现在有更多的开发人员正在使用Gradle。

更新:

这里我尝试了一些非常简单的方法:

变体1:

 android { productFlavors { } productFlavors['flavor1'] << { packageName "com.example.flavor1" } productFlavors['flavor2'] << { packageName "com.example.flavor2" } } /* A problem occurred evaluating root project 'MyProject'. > GroupableProductFlavorDsl with name 'flavor1' not found. */ 

变体2:

 android { productFlavors { } productFlavors['flavor1'] = { packageName "com.example.flavor1" } productFlavors['flavor2'] = { packageName "com.example.flavor2" } } /* no error, but does not work */ 

变体3:

 android { productFlavors { } productFlavors['flavor1'] = [packageName: "com.example.flavor1"] productFlavors['flavor2'] = [packageName: "com.example.flavor2"] } /* no error, but does not work */ 

所有这些都是一个主意 。

Solutions Collecting From Web of "dynamic生成产品口味"

通过反复试验解决:

 android { // let's assume these are return by a function which reads the filesystem def myFlavors = [ flavor1: [ packageName: "com.example.flavor1" ], flavor2: [ packageName: "com.example.flavor2" ] ] productFlavors { myFlavors.each { name, config -> "$name" { packageName config.packageName } } } } 

我知道已经有这个答案了,但是我把Chris.Zou的方法和TheHippo结合起来了。 并添加我自己的方法来做到这一点。

基本上,在处理风味时,我们通常使用包含资源的/ app / src /下的不同目录。 而且由于目录名称等于包名称,我只是列出了该文件夹下的目录(不包括“main”和“androidTest”)。

所以这里是我完整的工作gradle脚本:

 def map = [:] new File("./app/src").eachFile() { file-> def fileName = file.getName() if( fileName == "main" || fileName == "androidTest") { return } map.put(fileName, 'com.mypackagename.' + fileName ) } productFlavors { map.each { flavorName, packagename -> "$flavorName" { applicationId packagename } } } 

编辑:

  • 还想补充一点,com.mypackagename基本上是所有风味的根源。
  • 我有一个单独的脚本,复制粘贴风味目录到/ app / src /文件夹。

由于问题作者不想分享他的代码阅读文件。 我要写我做了什么。 我把所有的变体名称放在一个名为“app / build_variants.txt”的文件中,每行一行,如下所示:

 flavor1 flavor2 flavor3 flavor4 flavor5 

在“app / build.gradle”中:

 //...other configs... android { productFlavors { new File('app/build_variants.txt').eachLine { "$it" { resValue "string", "build_variant_name", "$it" } } } } //...other configs 

这将与下面的代码具有相同的结果:

 //...other configs... android { productFlavors { flavor1 { resValue "string", "build_variant_name", "flavor1" } flavor2 { resValue "string", "build_variant_name", "flavor2" } flavor3 { resValue "string", "build_variant_name", "flavor3" } flavor4 { resValue "string", "build_variant_name", "flavor4" } flavor5 { resValue "string", "build_variant_name", "flavor5" } } } //...other configs 

这里的关键是new File('app/build_variants.txt').eachLine { "$it" { resValue "string", "build_variant_name", "$it" } } 。 它读取文件'app / build_variants.txt',并为每一行生成一个产品的味道,它所读取的行中的名称。 $it是它传入的行。它只是groovy的闭包语法。 如果你想更深入的了解。 我强烈build议看@Daniel Lew关于groovy和gradle 的video 。 这很棒!。