【问题标题】:Passing properties to Android library project build file将属性传递给 Android 库项目构建文件
【发布时间】:2013-05-30 18:34:57
【问题描述】:

我有一个 Android 应用项目,它分为免费版和付费版。这两个项目共有的所有内容都位于一个名为“core”的 Android 库项目中。然后,我有付费版和免费版的实际 Android 应用项目。

我正在使用 Ant 脚本来构建这两个 APK。付费版本设置了一个属性,告诉“核心”项目付费版本正在构建。免费版告诉核心项目免费版正在构建中。

在 Google 决定发布 ADT 22 之前,它曾经工作得非常好。现在“核心”项目不再使用这些构建属性。

我怀疑库项目现在是在单独的 Ant 构建环境/进程中构建的。

所以这是我的问题:如何在应用项目的 build.xml 文件中为引用的 Android 库项目定义属性?如何将属性传递给这些库项目构建?

SDK 的 build.xml 文件中的什么地方实际编译了库项目?我想这将是正确的研究地点。

感谢您的宝贵时间。

【问题讨论】:

  • 您能描述一下这些属性的用途吗?也许有另一种解决方案......(附言我感到你的痛苦。我一直在努力解决完全相同的情况,试图在不复制太多代码的情况下构建一个应用程序的两个版本。)
  • @Code-Guru 我同意,这很痛苦。我记得半年前曾为此苦苦挣扎,每次当 ADT 获得重大更新时,您都必须重新编写构建脚本。回答您的问题:这些属性用于创建具有静态布尔标志的动态生成的 Java 类文件。这些标志用于打开/关闭核心项目中的代码部分。这两个标志是“IS_PAID_VERSION”用于激活许可验证代码,另一个“IS_DEBUG”用于激活非常详细的日志记录。
  • 我也遇到了同样的问题,最近有解决方案吗?
  • @nish1013 我在下面编辑了我的答案,以便更清楚地说明如何解决该问题。

标签: android ant build


【解决方案1】:

编辑澄清

您必须从 Android SDK(请参阅 SDK-Folder/tools/ant)创建原始 build.xml 文件的修改副本,并在 Google 通过合并差异(和当然保留自己的修改)。

build.xml 文件使用<subant> 任务构建库项目,该任务基本上会启动一个单独的构建环境,该环境不会自动查看调用范围的任何属性(这将是应用程序项目的构建环境)。

但是,在该subant 标记内,您可以使用<propertyset> 标记将调用方作用域的属性导出到库的构建XML。在您的build.xml 副本中查找以下代码块并进行如下修改:

....
            <echo level="info">Building Libraries with '${project.libraries.target}'...</echo>

            <!-- no need to build the deps as we have already
                 the full list of libraries -->
            <subant failonerror="true" buildpathref="project.library.folder.path" antfile="build.xml">

                <!-- *** ADD THIS: *** -->
                <propertyset id="project.library.buildargs">
                    <propertyref prefix="project.library.buildargs" />
                </propertyset>

                <target name="nodeps" />
                <target name="${project.libraries.target}" />
                <property name="emma.coverage.absolute.file" location="${out.absolute.dir}/coverage.em" />
            </subant>
....

以上示例使所有以project.library.buildargs. 为前缀的应用程序项目build.xml 属性对所有引用的Android 库构建脚本可见。

【讨论】:

  • 问题是如何设置/传递可从库 build.xml 访问的属性。在我的情况下,我需要将不同的环境从项目传递到库项目的 build.xml
  • @nish1013 你可能已经注意到我是提出原始问题的人。我的这个答案解决了这个问题。您必须创建原始 Android Ant build.xml 文件的副本(请参阅 Android SDK)并通过找到上面显示的代码块对其进行修改(回显行显示“使用...构建库”)。然后你需要在subant 任务中嵌入一个propertyset 标签。这会将内部定义的任何属性暴露给subant 任务构建环境(在本例中为所有Android 库项目)。只需在 propertyset 中添加一个 propertyref 标签,如我的回答所示。
  • 太糟糕了,它需要修改构建系统:(
【解决方案2】:

我发现为我的免费版本和付费版本提供不同价值的另一种解决方案是使用 [resources]。 Android 构建链允许应用程序项目覆盖共享库项目中设置的资源值。

因此,例如,您可以在res/values 的任何 XML 文件中拥有布尔资源:

<bool name="paid_version">false</bool>

当然,付费版在自己的res/values子目录下也有同样的资源,其值为true

然后从Activity 子类或任何其他具有Context 的类中,您可以执行以下操作:

if (getResources().getBoolean(R.id.paid_version)) {
    // Do the paid version code here
}

这具有相当容易实现的优点。不利的一面是,这是基于动态代码的运行时检查。这意味着当资源值设置为false 时,编译器或任何其他静态分析工具无法优化代码。

【讨论】:

  • 真是天才!但我想知道 ProGuard 是否能够在条件为“假”时去除这些代码部分。据我所知,它能够删除隐藏在 if 块中的“死”代码,这些代码总是评估为“假”。我相信它的工作要求是 if 语句条件不能包含变量引用或方法调用,以便可以在编译时对其进行评估。但无论如何,我会在未来的项目中考虑更简单的解决方案。你也可以用它来配置东西,比如设置 API 密钥或帮助页面的 URL 或类似的东西......可能性:-D
  • @NobuGames 这是一个很好的观点。我将在我的答案中编辑评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多