Java Gradle Android 依赖产品风味
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19013821/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Gradle Android dependency product flavors
提问by croc
I'd like to know if there is a way for a root project to define/inject some properties in it's dependencies. More specifically, the problem I'm having is that a library project has to know whether to take "free" or "pro" java sources and other resources before assemble/compile task is run. Kind of like specifying product flavors for library projects (that are inherited from it's parent project), but that isn't supported by the Android plugin for Gradle. Changing the library project structure, i.e. creating "free" and "pro" libs is not an option.
我想知道是否有办法让根项目在它的依赖项中定义/注入一些属性。更具体地说,我遇到的问题是,在运行汇编/编译任务之前,库项目必须知道是采用“免费”还是“专业”Java 源和其他资源。有点像为库项目(从它的父项目继承)指定产品风格,但 Android 插件不支持 Gradle。更改库项目结构,即创建“免费”和“专业”库不是一种选择。
Edit:The best I've managed to achieve so far is something like this:
编辑:到目前为止我设法实现的最好的东西是这样的:
root:build.gradle
根:build.gradle
android {
...
productFlavors {
free, pro
}
sourceSets {
free {
project(':..:lib') {
groupFreePro = 'free'
// java.srcDirs = ['src', 'free/src']
}
}
pro {
project(':..:lib') {
groupFreePro = 'pro'
// java.srcDirs = ['src', 'pro/src']
}
}
...
}
}
library:gradle.build
库:gradle.build
android {
...
sourceSets {
main {
java.srcDirs = [groupFreePro + '/src']
res.srcDirs = [groupFreePro + '/res']
}
}
...
}
}
That way I inject the groupFreePro variable into the lib project. But there is a problem with this approach:
这样我将 groupFreePro 变量注入到 lib 项目中。但是这种方法有一个问题:
By the time, when the lib project get's to it's android -> sourceSets task the groupFreePro is always set to "pro". I presume that's because all the sourceSets at the root project are read (and not just the one variant that I want to build with; "free" for example) and thus the last set/task always overrides any previously set values of groupFreePro.
到那时,当 lib 项目到达它的 android -> sourceSets 任务时,groupFreePro 始终设置为“pro”。我认为这是因为根项目中的所有 sourceSets 都被读取(而不仅仅是我想要构建的一个变体;例如“free”),因此最后一个 set/task 总是覆盖 groupFreePro 的任何先前设置的值。
If I try to set the value of groupFreePro any other way it either gets overriden (like in the above case), or I don't know the appropriate task/time/place where I should call this variable injection stuff to set the variable to the desired value. Uncommenting java.srcDirs
in root project doesn't help either.
如果我尝试以任何其他方式设置 groupFreePro 的值,它要么被覆盖(如上例所示),要么我不知道我应该调用此变量注入内容以将变量设置为的适当任务/时间/地点所需的值。java.srcDirs
在根项目中取消注释也无济于事。
I tried solving these problems on my own, but I'm really new to Gradle and also lack of proper documentation (at least for the Android part) leaves me guessing what to do most of the time so I do a lot of trial and error (but now I'm kind of stuck).
我尝试自己解决这些问题,但我对 Gradle 真的很陌生,而且缺乏适当的文档(至少对于 Android 部分)让我大部分时间都在猜测要做什么,所以我做了很多反复试验(但现在我有点卡住了)。
采纳答案by croc
This is how I've solved the problem for now. It's not a perfect solution, but it's good enough for now.
这就是我现在解决问题的方法。这不是一个完美的解决方案,但现在已经足够了。
Update!
更新!
I've updated the answer to include the latest 0.9.2 Gradle plugin and it's new(est) features (mostly just updated the library build scripts).
我已经更新了答案以包含最新的 0.9.2 Gradle 插件和它的新(est)功能(主要是更新了库构建脚本)。
root:gradle.build
根:gradle.build
// global variables
ext {
// can be set to default values or blank
groupFreePro = "free"
}
// start parameters
println "Start parametes: tasks = " + gradle.startParameter.getTaskNames()
gradle.startParameter.getTaskNames().each { task ->
if (task.contains("Free") || task.contains("F")) {
groupFreePro = "free"
} else if (task.contains("Pro") || task.contains("P")) {
groupFreePro = "pro"
}
println "groupFreePro = " + groupFreePro
}
android {
...
}
The task.contains("F")
is there to handle the abbreviated versions or running tasks (if we wanted to run the script as gradle aFD
).
的task.contains("F")
是,要想处理缩写版本或正在运行的任务(如果我们要运行脚本gradle aFD
)。
The global variables under ext
can be set to default values. In that case, even if you run the script without the "Free/Pro" in the task name, it should work just fine. The downside of default values is that the build may not crash if not set up properly (if you want the build to work only if "Free/Pro" in the task name is specified).
下面的全局变量ext
可以设置为默认值。在这种情况下,即使您在任务名称中没有“免费/专业版”的情况下运行脚本,它也应该可以正常工作。默认值的缺点是如果设置不正确,构建可能不会崩溃(如果您希望构建仅在任务名称中指定了“免费/专业”时才能工作)。
library:gradle.build
库:gradle.build
android {
...
defaultPublishConfig groupFreePro + groupDebugRelease.capitalize()
productFlavors {
free
pro
}
...
sourceSets {
main {
java.srcDirs = ['/src']
res.srcDirs = ['/res']
}
free {
java.srcDirs = ["free/src"]
res.srcDirs = ["free/res"]
}
pro {
java.srcDirs = ["pro/src"]
res.srcDirs = ["pro/res"]
}
}
...
}
dependencies {
freeCompile fileTree(dir: 'free/lib', include: '*.jar')
}
Update:
更新:
该库现在包含defaultPublishConfig
defaultPublishConfig
这样我不需要指定 java.srcDirs = ["src", groupFreePro + "/src"]
res.srcDirs = [groupFreePro + "/res"]
any more, as well as custom flavour compiling now be used i.e. flavor1Compile
(in the dependencies
block).
现在可以使用 ie flavor1Compile
(在dependencies
块中)以及自定义风味编译。
The option of writing compile project(path: ':project', configuration: 'flavor1Debug')
in the dependencies
block doesn't really work for us because you have to pass these options through dependencies and if you have multiple flavour groups/dimensions this means that more or less all of the flavour combinations have to be handled in "non-last" dependencies (i.e. dependencies that have other dependencies (that have multiple flavours)) as well.
compile project(path: ':project', configuration: 'flavor1Debug')
在dependencies
块中写入的选项对我们来说并不真正有效,因为您必须通过依赖项传递这些选项,并且如果您有多个风味组/维度,这意味着或多或少所有风味组合都必须在“非-last”依赖项(即具有其他依赖项(具有多种风格)的依赖项)。
The println
lines are just to see and make sure the right params are passed.
这些println
行只是为了查看并确保传递正确的参数。
The upsideof this solution (compared to Varun's) is that you need to run just one (original) task. That also means that it works (or at least it should) with Android Studio without any problems.
在上攻这一解决方案的(相对于Varun的的)是你需要运行只有一个(原始)任务。这也意味着它可以(或至少应该)与 Android Studio 一起使用而没有任何问题。
The downsideof this solution is that it doesn't work if you wanted to build all variants using gradle assemble
command (or alike) that is missing the Free
part of the task. I guess that could also be handled but I'm not doing that, because the current solution is good enough for me at the moment (though if I improve the current solution, I'll probably update this answer as well).
此解决方案的缺点是,如果您想使用gradle assemble
缺少Free
任务部分的命令(或类似方法)构建所有变体,则它不起作用。我想这也可以处理,但我没有这样做,因为目前的解决方案对我来说已经足够好了(尽管如果我改进当前的解决方案,我可能也会更新这个答案)。
There are other solutions possible by using gradle.taskGraph.whenReady
but I don't know how to properly set srcDirs
(of dependencies in particular). Suggestions welcome.
还有其他可能的解决方案,gradle.taskGraph.whenReady
但我不知道如何正确设置srcDirs
(特别是依赖项)。欢迎提出建议。
回答by Varun
Hereis the LibraryVariant
and hereis the ApkVariant
这是LibraryVariant
和这里是ApkVariant
Looking at the above DSL
it does not look like multiple productFlavors
is supported for the LibraryVariant
types..
从上面DSL
看productFlavors
,这些LibraryVariant
类型似乎不支持多个。
If your free/pro
are not going to change much you can create a aar
each for pro and free and use them as dependencies as needed by your app.
如果你free/pro
不打算改变太多,你可以aar
为 pro 和 free创建一个each 并根据你的应用程序的需要将它们用作依赖项。
UPDATE:
更新:
I have some code at github. It works but requires calling an additional task before the actual build/assemble task is called on the app. https://github.com/varunkochar/Trying-Android-Gradle/tree/master/FakeLibraryProductFlavors
我在 github 上有一些代码。它可以工作,但需要在应用程序上调用实际构建/组装任务之前调用附加任务。 https://github.com/varunkochar/Trying-Android-Gradle/tree/master/FakeLibraryProductFlavors
UPDATE:
更新:
With the latest android gradle plugin v0.9.0, the LibraryProject now also supports the same DSL as an ApplicationProject. So, you can use the latest version and use the inbuilt ability of library projects to build with custom flavors. Source: http://tools.android.com/tech-docs/new-build-system
使用最新的 android gradle 插件 v0.9.0,LibraryProject 现在也支持与 ApplicationProject 相同的 DSL。因此,您可以使用最新版本并使用库项目的内置功能来构建自定义风格。来源:http: //tools.android.com/tech-docs/new-build-system
回答by redDragonzz
Product flavors are now possible in android studio 0.5 (requires gradle plugin 0.9)
现在可以在 android studio 0.5 中使用产品口味(需要 gradle 插件 0.9)
So you can effectively write this DSL now:
所以你现在可以有效地编写这个 DSL:
android {
buildTypes {
debug {
}
release {
}
}
signingConfigs {
debug {
}
}
}
See: http://tools.android.com/tech-docs/new-build-system/migrating_to_09And http://tools.android.com/recent/androidstudio050released
请参阅:http: //tools.android.com/tech-docs/new-build-system/migrating_to_09和http://tools.android.com/recent/androidstudio050released
回答by jabbar_jigariyo
This feature is now available after Version 0.9 of the Gradle plugin for Android.
此功能在 Android 版 Gradle 插件 0.9 版之后可用。
Take a look here: http://tools.android.com/tech-docs/new-build-system/migrating_to_09
看看这里:http: //tools.android.com/tech-docs/new-build-system/migrating_to_09
Copy pasting here:
复制粘贴到这里:
Libraries
图书馆
The DSL for the library projects is now the same as for the application projects. This means you can create more build types, and create flavors.
- You can create/configure more build types, in the buildTypes { ... } container.
- You can create product flavors using the productFlavors { ... } container.
- You can create signingConfigs using the signingConfigs { ... } container.
库项目的 DSL 现在与应用项目的 DSL 相同。这意味着您可以创建更多构建类型,并创建风格。
- 您可以在 buildTypes { ... } 容器中创建/配置更多构建类型。
- 您可以使用 productFlavors { ... } 容器创建产品风味。
- 您可以使用signingConfigs { ... } 容器创建signingConfigs。
For example if you have in your library:
例如,如果您的图书馆中有:
android {
debug {
}
release {
}
debugSigningConfig {
}
}
You would replace it with:
您将替换为:
android {
buildTypes {
debug {
}
release {
}
}
signingConfigs {
debug {
}
}
}