6

这个问题是我另一个问题的延续,我想进一步改进。

我可以sourceSets使用以下代码对风味(具有通用配置)进行分组:

(从上面链接问题中的天才那里得到)

import com.android.build.gradle.api.AndroidSourceSet
android {
    sourceSets {
        [flavor2, flavor4].each { AndroidSourceSet ss ->
            ss.assets.srcDirs = ['repo-assets/flavor2']
            ss.res.srcDirs = ['repo-res/flavor2']
        }
    }
}

现在,我想知道是否[flavor2, flavor4]可以从以下任何一项中提取该列表:

  • 一个 XML 文件,我可以对其进行迭代以获得所有风​​格(我将放在那里)
  • 我可以迭代和获取值的 CSV 文件。
  • 一个自定义类,我可以将其写入单独的文件并从类中的静态成员中获取数据。

除了风味名称之外,我还打算将以下内容存储在外部源(以上之一)中:

  • 应用程序 ID(我将拉到productFlavors
  • 广告单元 ID(每种口味两个)
  • 其他一些自定义值,如类别等。

PORPOSE: 我想编写一段通用代码来迭代并动态创建productFlavorsand sourceSets。我已经概括sourceSets到几乎 90%,现在一个块足以满足所有口味。

现在看起来像这样:

sourceSets {
    [flavor1, flavor2, flavor3 ...].each { AndroidSourceSet ss ->
                ss.assets.srcDirs = ['repo-assets/' + ss.name.split('_')[0]]
                ss.res.srcDirs = ['repo-mipmap/' + ss.name.split('_')[0] , 'repo-strings/' + ss.name]
            }
}

也想为productFlavors上述提示做同样的事情。

卡在:[flavor2, flavor4]从外部来源获取上面代码中的列表(以及上面列出的每种风味的一些附加字段)。

我看到像这样的方法

productFlavors.add()
productFlavors.addAll()

但我不太确定如何使用这些。由于方法可用,我确信可以做我想做的事情。

有没有人这样做并有一些指示?

4

2 回答 2

10

我终于让它以这种方式工作:

在其中创建了一个自定义类MyFlavorbuild.gradle并将 csv 文件中的每种风味添加ArrayListMyFlavor

class MyFlavor {
    public String flavorname;
    public String basename;
    public String appid;
    public String bannerid;
    public String interstitialid;
    public String category;
}

def ArrayList<MyFlavor> myFlavors = new ArrayList<>();

new File('app/flavors.csv').eachLine {
    String[] values = "$it".split(',');
    MyFlavor f = new MyFlavor();
    f.flavorname = values[0];
    f.basename = values[0].split('_')[0];
    f.appid = values[1];
    f.bannerid = values[2];
    f.interstitialid = values[3];
    if(values[0].contains('_')) f.category= "state"
    else f.category = "country";
    myFlavors.add(f);
}

然后遍历ArrayList动态创建productFlavorsandsourceSets如下:

productFlavors {
    myFlavors.each { MyFlavor f ->
        "$f.flavorname" {
            applicationId = "$f.appid"
            buildConfigField 'String', 'BANNER_ID', "\"" + "$f.bannerid" + "\""
            buildConfigField 'String', 'INTERSTITIAL_ID', "\"" + "$f.interstitialid" + "\""
            buildConfigField 'String', 'CATEGORY', "\"" + "$f.category" + "\""
        }
    }
}
sourceSets {
    myFlavors.each { MyFlavor f ->
        "$f.flavorname" {
            assets.srcDirs = ['repo-assets/' + "$f.basename"]
            res.srcDirs = ['repo-mipmap/' + "$f.basename" , 'repo-strings/' + "$f.flavorname"]
        }

    }
}

希望这可以帮助某人。我成功地摆脱了 1000 行代码(因为我有很多口味)并将其缩减到您在此处看到的这 10 行代码。

于 2016-03-29T20:54:43.133 回答
2

要读取 XML 和 CSV 文件,您可以使用 Groovy 的全部功能。所有 Gradle 脚本都是用 Groovy 编写的。.each { Type var ->也是其中的一部分。第一个结果:https ://stackoverflow.com/a/2622965/253468 :

给定这样的 CSV 文件:

#name,appId,ad1,ad2,category
flavor1,app.id.flavor1,adunit1324523,adunit2234234,messenger
flavor2,app.id.flavor2,adunit42346451,adunit4562,editor
flavor3,app.id.flavor2.gpe,adunit345351,adunit3545342,messenger

Groovy 可以像这样加载它:

import com.android.build.gradle.BaseExtension
import com.android.build.gradle.api.AndroidSourceSet
import com.android.build.gradle.internal.dsl.ProductFlavor
// TODO get a real CSV parser, this is hacky
new File("flavors.csv").splitEachLine(",") { fields ->
    if (fields[0].charAt(0) == '#' as char) return; // skip comments
    def flavorName = fields[0];
    def baseName = flavorName.split('_')[0];
    def appId = fields[1];
    BaseExtension android = project.android // project.getExtensions().getByName('android'); 
    // productFlavors is declared as Collection, but it is a NamedDomainObjectContainer
    // if [flavorName] doesn't work, try .maybeCreate(flavorName) or .create(flavorName)
    ProductFlavor flavor = android.productFlavors[flavorName];
    AndroidSourceSet sourceSet = android.sourceSets[flavorName];
    flavor.applicationId = appId;
    sourceSet.res.srcDirs = [] // clear
    sourceSet.res.srcDir 'repo-mipmap/' + baseName
    sourceSet.res.srcDir 'repo-strings/' + flavorName
}

导入类型是为了可读性和代码完成,您可以替换任何变量类型,def它仍然可以工作。这些类型正是您进行常规android { ... }配置时使用的类型。内部类型可能随时更改,实际上我正在使用 1.5,它们可能已经在 2.0 中更改。

于 2016-03-29T18:17:05.943 回答