6

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.

Community
  • 1
  • 1
Jonik
  • 80,077
  • 70
  • 264
  • 372
  • If I comment out `sourceSets.internal` in the above config (and restore the app icon to its default place under `res`), Gradle starts noticing changes just fine again. So indeed the problem is related to the per-flavour resource dirs. – Jonik Jan 07 '14 at 15:10
  • I haven't looked at it in detail, but it sounds like it's worth filing a bug. – Scott Barta Jan 07 '14 at 16:42
  • @Scott: I looked around, and this looks like the same issue: https://code.google.com/p/android/issues/detail?id=60154 I left a comment there. – Jonik Jan 09 '14 at 15:04

2 Answers2

4

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.

Jonik
  • 80,077
  • 70
  • 264
  • 372
0

I have the several build flavors for the same app with some changes, icons & splash screens. Each flavor have its own res folder. When I build the apps, each apk sizes around 50 mb :(.

So I fixed the issue by updating the build.gradle file with the following

`    sourceSets {
        main {
//            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
//            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }
        prod {
            manifest.srcFile 'prod/AndroidManifest.xml'
            resources.srcDirs = ['src/prod/res']
        }
        dev {
            manifest.srcFile 'dev/AndroidManifest.xml'
            resources.srcDirs = ['src/dev/res']
        }

}`

In the above, I commented resources.srcDirs = ['src'] and added

           `prod {
                manifest.srcFile 'prod/AndroidManifest.xml'
                resources.srcDirs = ['src/prod/res']
            }
            dev {
                manifest.srcFile 'dev/AndroidManifest.xml'
                resources.srcDirs = ['src/dev/res']
            }`
Kushal Kumar
  • 173
  • 1
  • 14