Declaring res.srcDirs breaks Android Studio change detection of resource files

653 views Asked by At

We have multiple build variants in our Android client. We just started sharing source code and resources across build variants via custom source sets. This is what they look like:

sourceSets {
    internalDevelopment {
        java.srcDir('src/internal/java')
        java.srcDir('src/nonproduction/java')
        res.srcDirs = ['src/main/res', 'src/nonproduction/res'] // < --
    }
    internalStaging {
        java.srcDir('src/internal/java')
        java.srcDir('src/nonproduction/java')
        res.srcDirs = ['src/main/res', 'src/nonproduction/res']
    }
    internalProduction {
        java.srcDir('src/internal/java')
        java.srcDir('src/production/java')
        res.srcDirs = ['src/main/res', 'src/production/res']
    }
    externalProduction {
        java.srcDir('src/external/java')
        java.srcDir('src/production/java')
        res.srcDirs = ['src/main/res', 'src/production/res']
    }
}

The problem is that since introducing this pattern Android Studio does not respect changes we make to files under src/main/res

Meaning, I can go into one of my Activity's XML files, change a user-displayed String, deploy to my device, and no changes. Android Studio displays the preview of my changes to the XML without issue. I can even entirely invalidate the XML by deleting multiple elements referenced by the codebase; it deploys without any warnings or compile errors.

However, changes made to resource files under src/nonproduction/res are reflected upon a build/deploy.

--

What I've tried to fix this:

  1. Turning off parallel run / skipping installation if APK not changed.
  2. Clean and/or rebuild
  3. Delete .gradle folder
  4. Invalidated caches / restart

None of these consistently resolve the issue. To resolve it I have to change build variants, hope that works, and if not repeatedly try the above until I can actually see the change after a build. This is extremely painstaking to say the least.

By removing res.srcDirs = ['src/main/res', 'src/nonproduction/res'] the problem is immediately resolved and all my changes immediately take effect, but then I lose the value of the source sets.

Interestingly, even just specifying res.srcDirs = ['src/main/res'] is enough to cause this issue for me. I have to not declare any custom resource directories for my resource changes to consistently be recognized during a build/deploy.

Since I cannot share the entire project I've created a sample app that minimally reproduces the issue for me.

https://github.com/scb5304/resourcechangetest

Is this a known shortcoming of source sets or some issue with my configuration? Appreciate any guidance here.

2

There are 2 answers

0
Steve On

My solution to this was to add to srcDirs within the build-variant sourceSets, rather than specifying the entire array.

internalDevelopment {
    java.srcDir('src/internal/java')
    java.srcDir('src/nonproduction/java')
    res {
        srcDirs+= ['src/nonproduction/res'] // <--
    }
}
0
Anton Alexeev On

I was able to solve this issue by forcing MergeResources task to be always executed.

project.tasks.withType(MergeResources::class).configureEach {
    outputs.upToDateWhen { false }
}