Reputation: 4930
I want to override some strings in my res/strings.xml with gradle.
I know that since Android Gradle Plugin 0.7.+ theres the possibilty to have a variant specific source folder. But my app has a lot of flavors and I don't want to add additionally variant specific folders.
UPDATE 2014-01-17
What I want in detail:
I have some variables in my Resources that are depending only by the buildType (e.g. "release"). First I thought my SOLUTION_1 (override data after resources were merged) is nice, because if I have to change these variables I just have to change them in the build.config (just one place). But as Scott Barta wrote in the comment below there are some good reasons why this solution is NOT a good idea.
So i tried another solution SOLUTION_2 (just merge the right resources) based on this GitHub project of shakalaca. I think this way is more elegant and I still have the advantage just to change the variables in one place!
SOLUTION_1 (override data after resources were merged):
What I did in AS 0.4.2:
in build.gradle
I try to override the string "Hello World" to "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"
}
}
The copy and filter task works fine, but I couldn't set the "new" values.xml as string resource.
SOLUTION_2 (just merge the right resources)
merge this resourses with the flavor you want to build:
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']
}
}
Upvotes: 29
Views: 25033
Reputation: 2068
If anyone stumble upon this
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'
}
}
And to access those values using build variants:
if(!BuildConfig.LOG)
// do something with the boolean value
Or
view.setText(BuildConfig.yourkeyvalue);
Upvotes: 1
Reputation: 139
I don't believe you need to customize the build script at all to achieve what you want. According to my reading of http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants; when the build runs, resources will be merged from the following folders, if they exist;
src/[flavour][buildType]/res
src/[buildType]/res
src/[flavour]/res
src/main/res
So I believe you can achieve what you want by simply add the resources in src/release/res.
Though you can tweak the folder names by specifying the relevant sourceSets.[type].res.srcDirs if you really want to change them.
Upvotes: 8
Reputation: 80010
You should strive to come up with a solution that doesn't involve writing any custom code in your build files, especially code that does tricky things with reassigning source sets on the fly. Custom Gradle code is a little funky to write, and it's difficult to debug and maintain. The new build system is extremely powerful and already has tons of flexibility, and it's likely that you can already do what you want; it's just a matter of learning how.
Especially if you're just learning the ins and outs of Android-Gradle projects (and it's so new that we all are), it's best to try hard to work with the functionality built into the system before thinking outside the box.
Some recommendations:
debuggable
, jniDebugBuild
, renderscriptDebugBuild
, renderscriptOptimLevel
, packageNameSuffix
, versionNameSuffix
, signingConfig
, zipAlign
, runProguard
, proguardFile
, proguardFiles
. BuildConfig
mechanism for that sort of thing -- it's a Java class that defines a DEBUG
flag based on debug/release build status, and you can add your own custom Java code from different build types to do more meaningful things. BuildConfig
was intended for allowing small functional differences between build types, for cases where a debug build might want to perform some wasteful operation to assist in development, like doing more extensive data validation or creating more detailed debug logging, and those wasteful things are best optimized out of release builds. Having said that, it might be an appropriate mechanism to do what you want.Upvotes: 21