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'] } }
A build type determines how an app is packaged. By default, the Android plug-in for Gradle supports two different types of builds: debug and release . Both can be configured inside the buildTypes block inside of the module build file.
You can do this by adding extra properties to the ext block in the top-level build.gradle file. // of properties you can define. // You can also create properties to specify versions for dependencies.
The " allprojects " section is for the modules being built by Gradle. Oftentimes the repository section is the same for both, since both will get their dependencies from jcenter usually (or maybe maven central). But the "dependencies" section will be different.
Flavor Dimensions is a way to group flavors by a name. For now, we're using just a single group. Add the following line in your defaultConfig block: flavorDimensions "default" Now syncing the gradle would give you the following product flavors: Android Build Variants combine build types and product flavors.
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.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With