我想用 gradle 覆盖 res/strings.xml 中的一些字符串。
我知道自 Android Gradle 插件 0.7.+ 起 http://tools.android.com/tech-docs/new-build-system可能有一个特定于变体的源文件夹。
但我的应用程序有很多风格,我不想添加额外的变体特定文件夹。
更新2014-01-17
我想要的详细内容:
我的资源中有一些变量仅取决于构建类型(例如“release”)。
首先我以为我的解决方案_1(资源合并后覆盖数据)很好,因为如果我必须更改这些变量,我只需在 build.config 中更改它们(仅一处)。
但正如斯科特·巴塔(Scott Barta)在下面的评论中所写的那样,有一些充分的理由可以解释为什么这个解决方案不是一个好主意。
所以我尝试了另一种解决方案解决方案_2(只需合并正确的资源)基于shakalaca 的 GitHub 项目 https://github.com/shakalaca/learning_gradle_android/blob/082fa1575de1fa75ef09c90cb0cfdd60407e184d/07_tricks/app/build.gradle。我认为这种方式更优雅,而且我仍然有优势,只需更改中的变量one place!
SOLUTION_1(资源合并后覆盖数据):
我在 AS 0.4.2 中做了什么:
-
in build.gradle
我尝试将字符串“Hello World”覆盖为“OVERRIDE”(根据我在这篇文章中的回答 https://stackoverflow.com/questions/17465353/how-to-replace-a-string-for-a-buildvariant-with-gradle-in-android-studio):
android.applicationVariants.all{ variant ->
// override data in resource after merge task
variant.processResources.doLast {
overrideDataInResources(variant)
}
}
def overrideDataInResources(buildVariant){
copy {
// *** SET COPY PATHS ***
try {
from("${buildDir}/res/all/${buildVariant.dirName}") {
// println "... FROM: ${buildDir}/res/all/${buildVariant.dirName}"
include "values/values.xml"
}
} catch (e) {
println "... EXCEPTION: " + e
}
into("${buildDir}/res/all/${buildVariant.dirName}/values")
// println "... INTO: ${buildDir}/res/all/${buildVariant.dirName}/values"
// --- override string "hello_world"
filter {
String line ->
line.replaceAll("<string name=\"hello_world\">Hello world!</string>",
"<string name=\"hello_world\">OVERRIDE</string>");
}
// *** SET PATH TO NEW RES ***
buildVariant.processResources.resDir = file("${buildDir}/res/all/${buildVariant.dirName}/values/values/values.xml")
// println "... NEW RES PATH: " + "${buildDir}/res/all/${buildVariant.dirName}/values/values/values.xml"
}
}
复制和过滤任务工作正常,但我无法将“新”values.xml 设置为字符串资源。
SOLUTION_2(只需合并正确的资源)
您应该努力提出一个不涉及在构建文件中编写任何自定义代码的解决方案,尤其是那些通过动态重新分配源集来完成棘手事情的代码。自定义 Gradle 代码编写起来有点时髦,并且难以调试和维护。新的构建系统非常强大,并且已经具有大量的灵活性,并且您很可能已经可以做您想做的事情;这只是学习方法的问题。
特别是如果您刚刚学习 Android-Gradle 项目的来龙去脉(而且它对我们来说都是新事物),最好在跳出框框思考之前努力尝试使用系统内置的功能。
一些建议:
- 您不太可能需要根据构建类型改变资源。 Android-Gradle 中的构建类型应该类似于调试或发布,其区别在于可调试性、编译器优化或签名;构建类型应该在功能上彼此等效。如果你看一下您可以通过 Groovy DSL 在构建类型上设置属性 http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Types,你可以看到意图:
debuggable
, jniDebugBuild
, renderscriptDebugBuild
, renderscriptOptimLevel
, packageNameSuffix
, versionNameSuffix
, signingConfig
, zipAlign
, runProguard
, proguardFile
, proguardFiles
.
- 如果您仍然认为想要根据构建类型改变资源,那么使用当前的构建系统已经有一种简单的方法可以做到这一点。您可以拥有一个特定于构建类型的资源目录,将资源放在那里,构建系统中的资源合并将在构建时为您处理好事情。这是 Android/Gradle 中强大的功能之一。看使用构建风格 - 正确构建源文件夹和 build.gradle https://stackoverflow.com/questions/16737006/using-build-flavors-structuring-source-folders-and-build-gradle-correctly有关如何使其发挥作用的信息。
- 如果您想根据构建类型更改某些内容,并且您的需求非常快速且简单,那么您可能希望在 Java 代码中而不是资源中或在构建系统中进行切换。有的是
BuildConfig
这类事情的机制——它是一个 Java 类,它定义了一个DEBUG
基于调试/发布构建状态进行标记,并且您可以添加来自不同构建类型的自定义 Java 代码来执行更有意义的操作。BuildConfig
旨在允许构建类型之间存在较小的功能差异,适用于调试构建可能想要执行一些浪费的操作来协助开发的情况,例如进行更广泛的数据验证或创建更详细的调试日志记录,而这些浪费的事情最好被优化掉发布版本。话虽如此,这可能是一种适合您想做的事情的机制。
- 考虑对您目前使用的构建类型使用风格。从概念上讲,风格有点像构建类型,因为它是可以构建的应用程序的另一种变体;构建系统将创建口味与构建类型的矩阵,并且可以构建所有组合。然而,风格针对不同的用例,其中不同的风格共享大部分代码,但可能具有显着的功能差异。一个常见的例子是应用程序的免费版本与付费版本。由于应用程序不同变体中的不同资源代表不同的功能,这可能表明需要不同的风格。风味可以有不同的资源目录,这些目录在构建时以与构建配置相同的方式合并;请参阅上面链接的问题以获取更多信息。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)