我想用gradle覆盖res / strings.xml中的一些字符串。
我知道since Android Gradle Plugin 0.7.+有可能拥有一个变体特定的源文件夹。 但我的应用程序有很多风格,我不想添加额外的变体特定文件夹。
更新2014-01-17
我想要的详细信息:
我的资源中有一些变量只依赖于buildType(例如“release”)。 首先我认为我的 SOLUTION_1 (在资源合并后覆盖数据)很不错,因为如果我必须更改这些变量,我只需要在build.config中更改它们(只需一个地方)。 但正如Scott Barta在下面的评论中写道,为什么这个解决方案不是一个好主意有一些很好的理由。
所以我尝试了基于this GitHub project of shakalaca的其他解决方案 SOLUTION_2 (只是合并正确的资源)。我认为这种方式更优雅,我仍然有优势只是改变一个的变量!
SOLUTION_1(合并资源后覆盖数据):
我在AS 0.4.2中做了什么:
build.gradle
中的我尝试将字符串“Hello World”覆盖为“OVERRIDE”(based on my answer at this post):
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"
}
}
复制和过滤任务工作正常,但我无法将“new”values.xml设置为字符串资源。
SOLUTION_2(只需合并正确的资源)
将此资源与您要构建的风格合并:
android.applicationVariants.all{ variant ->
variant.mergeResources.doFirst{
checkResourceFolder(variant)
}
}
def checkResourceFolder(variant){
def name = variant.name;
if(name.contains("Release")){
android.sourceSets.release.res.srcDirs = ['src/releaseRes/res']
android.sourceSets.flavor1.res.srcDirs = ['src/flavor1/res']
}
}
答案 0 :(得分:18)
您应该努力提出一种解决方案,该解决方案不涉及在构建文件中编写任何自定义代码,特别是在动态重新分配源集时执行棘手操作的代码。自定义Gradle代码编写起来有点时髦,而且很难调试和维护。新的构建系统非常强大,已经具有很大的灵活性,很可能你已经可以做你想做的事了;这只是学习方法的问题。
特别是如果您只是学习Android-Gradle项目的细节(并且它是如此新颖以至于我们都是),最好在开箱即用之前尽力使用系统内置的功能。
一些建议:
debuggable
,jniDebugBuild
,renderscriptDebugBuild
,renderscriptOptimLevel
,packageNameSuffix
,{{1 },versionNameSuffix
,signingConfig
,zipAlign
,runProguard
,proguardFile
。 proguardFiles
机制 - 它是一个基于调试/发布构建状态定义BuildConfig
标志的Java类,您可以从不同的构建类型添加自己的自定义Java代码做更有意义的事情。 DEBUG
旨在允许构建类型之间的小功能差异,适用于调试版本可能需要执行一些浪费操作以协助开发的情况,例如进行更广泛的数据验证或创建更详细的调试日志记录,以及那些浪费在发布版本中最好地优化了一些东西。话虽如此,它可能是一个适当的机制来做你想要的。答案 1 :(得分:6)
我不相信您需要自定义构建脚本才能实现您的目标。根据我对http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants的解读;当构建运行时,资源将从以下文件夹合并(如果存在);
src/[flavour][buildType]/res
src/[buildType]/res
src/[flavour]/res
src/main/res
所以我相信你只需在src / release / res。
中添加资源就可以达到你想要的效果虽然你可以通过指定相关的sourceSets调整文件夹名称。[type] .res.srcDirs如果你真的想要更改它们。
答案 2 :(得分:1)
如果有人偶然发现了这个
buildTypes {
debug{
buildConfigField "String", "Your_string_key", '"yourkeyvalue"'
buildConfigField "String", "SOCKET_URL", '"some text"'
buildConfigField "Boolean", "LOG", 'true'
}
release {
buildConfigField "String", "Your_string_key", '"release text"'
buildConfigField "String", "SOCKET_URL", '"release text"'
buildConfigField "Boolean", "LOG", 'false'
}
}
使用构建变体访问这些值:
if(!BuildConfig.LOG)
// do something with the boolean value
或者
view.setText(BuildConfig.yourkeyvalue);