【问题标题】:Gradle Android dependency product flavorsGradle Android 依赖产品风格
【发布时间】:2013-10-01 13:41:35
【问题描述】:

我想知道根项目是否有办法在其依赖项中定义/注入一些属性。更具体地说,我遇到的问题是库项目必须知道在运行组装/编译任务之前是采用“免费”还是“专业”Java 源代码和其他资源。有点像为库项目(从它的父项目继承)指定产品风格,但 Gradle 的 Android 插件不支持。更改库项目结构,即创建“免费”和“专业”库不是一种选择。

编辑: 到目前为止,我取得的最好成绩是这样的:

root: 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']
            }
        }
    ...
    }
}

库: gradle.build

android {
    ...
    sourceSets {
        main {
                  java.srcDirs = [groupFreePro + '/src']
                  res.srcDirs = [groupFreePro + '/res']
             }
        }
    ...
    }
}

这样我将 groupFreePro 变量注入到 lib 项目中。但是这种方法有一个问题:

当 lib 项目进入它的 android -> sourceSets 任务时,groupFreePro 总是设置为“pro”。我认为这是因为根项目中的所有源集都已读取(而不仅仅是我想要构建的一个变体;例如“免费”),因此最后一个集/任务总是覆盖任何先前设置的 groupFreePro 值。

如果我尝试以任何其他方式设置 groupFreePro 的值,它要么被覆盖(如上述情况),要么我不知道我应该调用这个变量注入东西的适当任务/时间/地点来设置变量到所需的值。在根项目中取消注释 java.srcDirs 也无济于事。

我尝试自己解决这些问题,但我对 Gradle 真的很陌生,而且缺乏适当的文档(至少对于 Android 部分)让我大部分时间都在猜测该怎么做,所以我做了很多反复试验(但现在我有点卡住了)。

【问题讨论】:

  • 您是否尝试过将“库”项目设为普通项目。 gradle 的依赖管理意味着你可以像使用库项目一样使用任何项目。
  • 我有,但是我在构建时遇到了其他问题。我认为问题在于,作为普通项目构建的其他库生成了构建系统(或我)不知道如何将其包含到主项目/APK 中的 APK。不过我可能会再试一次,看看我能不能换一种方式。
  • 您可以共享该设置的代码吗?
  • 您希望我分享代码的具体设置是什么?将库作为项目构建的那个?
  • 抱歉回复晚了...我的意思是您使用标准项目依赖项而不是库依赖项的代码。我认为很明显,图书馆不可能做到这一点。我已经用ant 做了类似的事情,但必须研究一个 gradle 实现。

标签: java android groovy gradle android-studio


【解决方案1】:

这就是我现在解决问题的方法。这不是一个完美的解决方案,但现在已经足够了。

更新!

我已经更新了答案以包含最新的 0.9.2 Gradle 插件和它的新(est)功能(大部分只是更新了库构建脚本)。

root: 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 {
...
}

task.contains("F") 用于处理缩写版本或运行任务(如果我们想以gradle aFD 运行脚本)。

ext下的全局变量可以设置为默认值。在这种情况下,即使您运行任务名称中没有“Free/Pro”的脚本,它也应该可以正常工作。默认值的缺点是,如果设置不正确,构建可能不会崩溃(如果您希望构建只有在任务名称中指定了“Free/Pro”时才能工作)。

库: 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')
}

更新:

库现在包含 defaultPublishConfig,所以我不需要指定
        java.srcDirs = ["src", groupFreePro + "/src"]
        res.srcDirs = [groupFreePro + "/res"]

现在可以使用自定义风味编译,即flavor1Compile(在dependencies 块中)。

dependencies 块中写入compile project(path: ':project', configuration: 'flavor1Debug') 的选项对我们来说实际上不起作用,因为您必须通过依赖项传递这些选项,如果您有多个风味组/维度,这意味着或多或少所有风味组合也必须在“非最后”依赖项(即具有其他依赖项(具有多种风味)的依赖项)中处理。



println 行只是为了查看并确保传递了正确的参数。

此解决方案的优势(与 Varun 相比)是您只需要运行一个(原始)任务。这也意味着它可以(或至少应该)与 Android Studio 一起工作而没有任何问题。

此解决方案的缺点是,如果您想使用缺少任务的Free 部分的gradle assemble 命令(或类似命令)构建所有变体,则它不起作用。我想这也可以处理,但我没有这样做,因为目前的解决方案对我来说已经足够好了(尽管如果我改进当前的解决方案,我可能也会更新这个答案)。

使用gradle.taskGraph.whenReady 可能还有其他解决方案,但我不知道如何正确设置srcDirs(特别是依赖项)。欢迎提出建议。

【讨论】:

  • @croc 感谢您发布此信息。 :D 让它更容易。
  • 我已经稍微更新了答案,以包含新的 0.9.2 Gradle 插件可能进行的更改。欢迎提出建议/cmets。
【解决方案2】:

HereLibraryVarianthereApkVariant

查看上面的DSLLibraryVariant 类型似乎不支持多个productFlavors..

如果您的free/pro 不会发生太大变化,您可以为专业版和免费版分别创建一个aar,并根据您的应用程序的需要将它们用作依赖项。

更新:

我在 github 上有一些代码。它可以工作,但需要在应用程序调用实际的构建/组装任务之前调用一个额外的任务。 https://github.com/varunkochar/Trying-Android-Gradle/tree/master/FakeLibraryProductFlavors

更新:

使用最新的 android gradle 插件 v0.9.0,LibraryProject 现在 还支持与 ApplicationProject 相同的 DSL。所以,你可以使用 最新版本并使用库项目的内置功能 使用自定义口味构建。 来源:http://tools.android.com/tech-docs/new-build-system

【讨论】:

  • 请看我的编辑,我已经扩展了我的问题。不幸的是,您的建议不足以让我找到一个可行的解决方案。你能给我提供一个 build.gradle 脚本的工作示例吗?
  • @croc 看看这里。 groups.google.com/forum/#!topic/adt-dev/wjH5M7dPo-0 看起来有人已经把这个带到了 adt-dev 团队。希望这将在以后的某个时候得到支持。
  • @croc 我已经上传了一些代码到 GitHub。 github.com/varunkochar/Trying-Android-Gradle/tree/master/…。这是一个不好的解决方法。需要在编译应用代码之前调用额外的 gradle 任务。
  • @croc 积分我有很多。 :) 只是想帮助解决这个问题,因为许多其他开发人员可能面临这个问题。在将我的答案标记为已接受之前,您可能已经等待,因为其他人可能会想出更好的方法。
  • 我知道 :PI 已经考虑过了,但是既然你帮助了我并且赏金已经开始,我认为给你赏金也是公平的 :) 至于答案,如果有人会来有一个更好的解决方案,我以后仍然可以接受。
【解决方案3】:

此功能现在在 Android 版 Gradle 插件 0.9 版之后可用。

看这里:http://tools.android.com/tech-docs/new-build-system/migrating_to_09

复制粘贴到这里:

库项目的 DSL 现在与应用程序项目的 DSL 相同。这意味着您可以创建更多构建类型并创建风味。
- 您可以在 buildTypes { ... } 容器中创建/配置更多构建类型。
- 您可以使用 productFlavors { ... } 容器创建产品风味。
- 您可以使用signingConfigs { ... } 容器创建signingConfigs。

例如,如果您的图书馆中有:

android {
    debug {
    }
    release {
    }
    debugSigningConfig {
    }
}

您可以将其替换为:

android {
    buildTypes {
        debug {
        }
        release {
        }
    }
    signingConfigs {
        debug {
        }
    }
}

【讨论】:

  • 我知道,我正在调查。
【解决方案4】:

现在可以在 android studio 0.5 中使用产品风格(需要 gradle 插件 0.9)

所以你现在可以有效地编写这个 DSL:

android {
    buildTypes {
        debug {
        }
        release {
        }
    }
    signingConfigs {
        debug {
        }
    }
}

见:http://tools.android.com/tech-docs/new-build-system/migrating_to_09 还有http://tools.android.com/recent/androidstudio050released

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-02
    • 2013-06-11
    • 1970-01-01
    • 2014-11-10
    • 1970-01-01
    • 2014-04-14
    • 2023-03-17
    相关资源
    最近更新 更多