我创建了一个Android应用程序,需要构建多种(30多种)风格。
我的想法是直接从我的productFlavors
目录中的文件夹结构生成不同的src
,因为配置总是非常相似(基本上只是另一个packageName,一个新的启动器图标和一些字符串更改)。
src
文件夹如下所示:
└── src
├── flavor1
│ ├── flavor2.keystore
│ ├── res
├── flavor2
│ ├── res
│ ├── flavor2.keystore
└── main
├── AndroidManifest.xml
├── java
└── res
如果我必须手动创建gradle属性,它看起来会像这样:
android {
....
productFlavors {
flavor1 {
packageName 'com.example.flavor1'
}
flavor2 {
packageName 'com.example.flavor2'
}
}
}
每次我尝试在创建后更改productFlavors
配置时,我都会收到错误或无提示忽略更改/添加。
这可能是我造成的问题,因为我的Gradle / Groovy体验非常有限,或者这是不可能的。
我大多得到错误,说GroupableProductFlavorDsl_Decorated
无法按照我想要的方式进行操作。
我试图存档的内容应该是这样的:
android {
....
def flavors = getMyFlavorsFromFileSystem()
productFlavors {
}
flavors.each { name, config ->
productFlavors[name] << config
}
}
注意:我知道这个问题基本上是旧版问题的duplicate,遗憾的是从来没有回答过。由于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
*/
所有这些都是Gist。
答案 0 :(得分:19)
通过反复试验解决:
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
}
}
}
}
答案 1 :(得分:6)
我知道已有答案,但我将Chris.Zou的方法与TheHippo结合起来。并添加我自己的方法来做到这一点。
基本上,在处理flavor时,我们通常使用包含资源的/ 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
}
}
}
编辑:
答案 2 :(得分:3)
由于问题作者不想分享他的代码来阅读文件。我要写下我的所作所为。我将所有变体名称放在名为“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的闭包语法。如果你想要更深刻的理解。我强烈建议您观看@Daniel Lew's video关于groovy和gradle的内容。太棒了!。