I, quite innocently, switched to using different app icons for each product flavour along these lines:
sourceSets.production {
res.srcDirs = ['res', 'res-production']
}
sourceSets.beta {
res.srcDirs = ['res', 'res-beta']
}
sourceSets.internal {
res.srcDirs = ['res', 'res-internal']
}
Thing is, after that, Gradle stopped noticing changes in any layout files, such as res/layout/activity_faq.xml
, and requires a clean build each time, if I want my XML changes to be included in the APK.
I first thought this was an Android Studio problem, but in fact I can reproduce it with pure Gradle, on the command line, simply looking at the files that appear under build/res/all/internal/debug/layout
.
When I run ./gradlew assembleInternalDebug
, it outputs:
:compileInternalDebugNdk UP-TO-DATE
:preBuild UP-TO-DATE
:preInternalDebugBuild UP-TO-DATE
:prepareInternalDebugDependencies
:compileInternalDebugAidl UP-TO-DATE
:compileInternalDebugRenderscript UP-TO-DATE
:generateInternalDebugBuildConfig UP-TO-DATE
:mergeInternalDebugAssets UP-TO-DATE
:mergeInternalDebugResources
:processInternalDebugManifest UP-TO-DATE
:processInternalDebugResources UP-TO-DATE
:generateInternalDebugSources UP-TO-DATE
:compileInternalDebugJava UP-TO-DATE
:preDexInternalDebug UP-TO-DATE
:dexInternalDebug UP-TO-DATE
:processInternalDebugJavaRes UP-TO-DATE
:validateDebugSigning
:packageInternalDebug UP-TO-DATE
:assembleInternalDebug UP-TO-DATE
BUILD SUCCESSFUL
Here, processInternalDebugResources
is shown to be UP-TO-DATE
, while I think it should not be, when there are changed resource files. Before the icon-per-flavour change, in similar Gradle output, processInternalDebugResources
was not shown up-to-date.
Question is, any way to fix this, or did I stumble upon a bug in Android Gradle plugin?
My build.gradle
:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.7.3'
}
}
apply plugin: 'android'
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.code.gson:gson:2.2.4'
compile 'com.google.guava:guava:15.0'
compile 'com.netflix.rxjava:rxjava-core:0.14.2'
compile 'com.netflix.rxjava:rxjava-android:0.14.2'
compile 'com.squareup.okhttp:okhttp:1.2.1'
compile 'com.android.support:support-v4:13.0.0'
compile 'com.android.support:support-v13:13.0.0'
}
android {
compileSdkVersion 19
buildToolsVersion "19"
defaultConfig {
minSdkVersion 14
targetSdkVersion 19
}
productFlavors {
production {
packageName "fi.company.app"
}
beta {
packageName "fi.company.app.beta"
}
internal {
packageName "fi.company.app.internal"
}
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
// Move the tests to tests/java, tests/res, etc...
instrumentTest.setRoot('tests')
debug.setRoot('build-types/debug')
release.setRoot('build-types/release')
}
// Custom res directories for different flavors; used for
// setting different app icon.
sourceSets.production {
res.srcDirs = ['res', 'res-production']
}
sourceSets.beta {
res.srcDirs = ['res', 'res-beta']
}
sourceSets.internal {
res.srcDirs = ['res', 'res-internal']
}
signingConfigs {
release {
// ...
}
}
buildTypes {
release {
signingConfig signingConfigs.release
// ...
}
}
}
Gradle 1.9; Android Gradle plugin 0.7.3.
Edit: For other reasons, I switched from product flavours to custom build types for my app icon customisation needs. This problem still remains, so at least this isn't product flavour specific.
Parallel executionBy using the --parallel switch, you can force Gradle to execute tasks in parallel as long as those tasks are in different projects. You could see big improvements in build times as soon as you enable parallel builds.
Compile projects in parallelIn parallel mode, Gradle will run multiple executor threads, which can execute tasks from different projects in parallel. By default Gradle will create one executor thread for each CPU core on your machine, but this is configurable.
In addition, there are two options for profiling your build outside of Android Studio: The standalone gradle-profiler tool, a robust tool for deep analysis of your build. The Gradle --profile option, a convenient tool available from the Gradle command line.
Build types define certain properties that Gradle uses when building and packaging your app, and are typically configured for different stages of your development lifecycle.
Ok, got this fixed. It turned out to be a small problem in my build.gradle
.
What helped me was trying to upgrade to Gradle plugin 0.9.0, after which I started getting errors like these:
* What went wrong:
A problem occurred configuring root project 'MyProject'.
> SourceSets 'debug' and 'main' use the same file/folder for 'res': /path/to/MyProject/res
Well, I simply tried removing res.srcDirs = ['res']
from main sourceSets, and that was it.
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
// res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
// ...
}
I left the rest of the sourceSets definitions untouched (res.srcDirs = ['res', 'res-beta']
for sourceSets.beta
and so on).
Everything works again: the build type (or product flavour) specific custom icons are in use, and Gradle once again correctly notices changes to resource files (e.g. layouts) in incremental builds!
(I verified that the problem indeed was in my config by testing with Gradle plugin versions 0.8.1, 0.9.0 and 0.9.3 with my changed build.gradle
. Indeed, changes in the plugin were not what fixed this, even if 0.9.0 was the version that started giving me the useful error message.)
Possibly the root cause here was using "old project structure" and build.gradle
that was originally generated by Eclipse. In any case, studying source sets and project structure more carefully in the User Guide might have helped too.
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