5

可以说我有以下内容sourceSets

sourceSets {
    flavor1 {
        assets.srcDirs = ['repo-assets/flavor1']
        res.srcDirs = ['repo-res/flavor1']
    }
    flavor2 {
        assets.srcDirs = ['repo-assets/flavor2']
        res.srcDirs = ['repo-res/flavor2']
    }
    flavor3 {
        assets.srcDirs = ['repo-assets/flavor1']
        res.srcDirs = ['repo-res/flavor1']
    }
    flavor4 {
        assets.srcDirs = ['repo-assets/flavor2']
        res.srcDirs = ['repo-res/flavor2']
    }
}

如果您注意到flavor1flavor3具有相同的 srcDirsflavor2flavor4.


尝试可能性#1

我试图弄清楚是否有办法通过使用这样的东西来避免冗余:

sourceSets {
    flavor1, flavor3 {
        assets.srcDirs = ['repo-assets/flavor1']
        res.srcDirs = ['repo-res/flavor1']
    }
    flavor2, flavor4 {
        assets.srcDirs = ['repo-assets/flavor2']
        res.srcDirs = ['repo-res/flavor2']
    }
}

以上不起作用(已经尝试过)。寻找类似的东西,这样我就可sourceDirs以为一组口味提供一组通用的。任何人都尝试做类似的事情并可以提供一些指示?


尝试可能性#2

sourceSets需要和口味的名称相同吗?

我可以sourceSets单独命名然后将它们映射到productFlavors这样吗?

productFlavors {
    flavor1 {
      sourceset = "src1"
    }
    flavor2 {
      sourceset = "src2"
    }
    flavor3 {
      sourceset = "src1"
    }
    flavor4 {
      sourceset = "src2"
    }
}

sourceSets {
    src1 {
    }
    src2 {
    }
}

尝试可能性#3

可以通过任务以某种方式动态分配源集以实现相同的目标吗?


更新

道格拉斯的回答有点帮助我非常接近我最终寻找的东西(减少 build.gradle 中的代码)。他使用了上面的可能性#3。谢谢道格拉斯!赏金猎人的任何更好的选择仍然是受欢迎的(更接近上面的可能性#1和#2)。如果没有任何结果,当我接受他的回答时,道格拉斯已经在这段时间结束时获得了赏金。但仍会对找到更好的选择保持乐观。

4

3 回答 3

6

You were also pretty close with your first possibility:

sourceSets {
    [flavor1, flavor3].each {
        it.assets.srcDirs = ['repo-assets/flavor1']
        it.res.srcDirs = ['repo-res/flavor1']
    }
    [flavor2, flavor4].each {
        it.assets.srcDirs = ['repo-assets/flavor2']
        it.res.srcDirs = ['repo-res/flavor2']
    }
}

The above doesn't look nice in IDEA editor, a lot of warnings are shown. You can set the type if you want to get code completion:

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']
        }
    }
}

Another trick: this way the definition of the flavor is co-located with the source set listing.

android
    productFlavors {
        flavor1 {
            applicationId "flavor1.app.id"
        }
        flavor2 {
            applicationId "flavor2.app.id"
        }
        [flavor1, flavor2].each {
            sourceSets[it.name].assets.srcDirs = ['repo-assets/flavor1']
            sourceSets[it.name].res.srcDirs = ['repo-assets/flavor1']
        }
    }

Whichever way you go there's also a noteworthy thing about srcDirs, see source:

println assets.srcDirs // say it's [src/flavor/assets]
assets.srcDirs = ['dir1', 'dir2'] // overwrites existing directories: output would be [dir1, dir2]
assets.srcDirs 'dir1', 'dir2' // appends existing directories: output would be [src/flavor/assets, dir1, dir2]
assets.srcDir 'dir1' // appends only one dir, output would be [src/flavor/assets, dir1]
于 2016-03-28T23:51:04.823 回答
2

我认为@jmols 在评论中想说的是这样的:

从结构出发

repo-assets
    flavor1
    flavor2
repo-res
    flavor1
    flavor2

flavor1
    assets
    res
flavor2
    assets
    res

并使用

sourceSets {
    //flavor1.setRoot('flavor1') // default
    //flavor2.setRoot('flavor2') // default
    flavor3.setRoot('flavor1')
    flavor4.setRoot('flavor2')
}

有关默认结构,请参阅http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Project-Structure 。setRoot这是 的源代码setRoot,请注意它会重置所有自定义,这就是匹配默认结构至关重要的原因。它的内置调用位于此处

于 2016-03-28T23:32:47.147 回答
1

您可以定义一个函数来复制风味(在 之外android {}):

def copyFlavor(flavordest, flavororig) {
    flavordest.resources.srcDirs = flavororig.resources.srcDirs
    flavordest.res.srcDirs = flavororig.res.srcDirs
    flavordest.aidl.srcDirs = flavororig.aidl.srcDirs
    flavordest.java.srcDirs = flavororig.java.srcDirs
    flavordest.assets.srcDirs = flavororig.assets.srcDirs
    flavordest.renderscript.srcDirs = flavororig.renderscript.srcDirs

    // if you don't need all of this, remove them. There are much more too, like `jni` and `jniLibs`
}

然后在源集上调用此函数:

sourceSets {
    copyFlavor(flavor3, flavor1)  // flavor3 = flavor1
    copyFlavor(flavor4, flavor2)  // flavor4 = flavor2
}

当然,只有当你有多种口味时才值得,只有两种,编写函数的开销更大。

编辑: 添加我使用的项目结构

为了简化并且不需要指定flavor1 和flavor2 路径,我使用了flavors 的标准结构:

app/
    src/
        androidTest/
        flavor1/
            assets/
            res/
                values/strings.xml
        flavor2/
            assets/
            res/
                values/strings.xml
        main/
            assets/
            java/
            res/
                values/strings.xml
        test/

values.xml有一个app_name内容"SourceSets"为 for main"SourceSets 1"forflavor1"SourceSets 2"for的字符串flavor2

只需以标准方式定义 flavor1 和 flavor2 路径,然后使用提供的函数复制它们。

编辑 2: 我尝试过的事情,可能有些会起作用,但这里没有做(可能我犯了一些愚蠢的错误)

我试过但没有用的东西:

A:
1. flavor3.root = "flavor1"
2. flavor3.root = "flavor1/"
3. flavor3.setRoot("flavor1")
4.flavor3.setRoot("flavor1/")
这些都编译好了,但是我定义的要测试的字符串资源没有改变。

B:
flavor3.root = flavor1.root
这甚至不编译,.root是只写的。

C:
flavor3.root = flavor1
这也编译了,但没有效果。请注意,它与A不同,因为在A中,右侧是一个字符串。

D:
我也有这个想法[].each,但是当我尝试的时候,我可能犯了一些愚蠢的错误,它也没有奏效:

    [flavor2, flavor4].each {
        it.res.srcDirs = ["flavor2/res"]
        it.resources.srcDirs = ["flavor2/res"]
        it.assets.srcDirs = ["flavor2/assets"]
    }

最后一个我有一些希望,但无法管理。然后我坚持这个copyFlavor功能。以上所有我也尝试使用前置src(例如,src/flavor1),但不成功。

于 2016-03-28T04:18:13.103 回答