Is there a reasonably simple way for a module's build.gradle
file to indicate that certain files from a dependency should be excluded? I am specifically interested in excluding certain resources from an AAR.
LeakCanary is an interesting library for helping to track down memory leaks. However, it has an undocumented requirement of compileSdkVersion
of 21 or higher. While most projects should not have a problem with this, it's unseemly for a library to require a certain compileSdkVersion
without a good reason. A development team may have frozen their compileSdkVersion
as part of a general policy to only change those sorts of settings as part of major version updates of their app or something.
In this case, for v1.3.1 of LeakCanary at least, the only reason compileSdkVersion
is required, AFAICT, is because the AAR has a res/values-v21/
directory, containing a theme definition that inherits from Theme.Material
. This theme is used by a diagnostic activity. That activity is never seen by end users, only by developers in debug
builds. Frankly, what that activity looks like, theme-wise, does not really matter. Forcing a compileSdkVersion
of 21 just to have that diagnostic activity have a certain theme is, IMHO, stupid.
It'd be nice if as part of a compile
directive we could say "hey, please skip res/values-v21/
from this AAR, m'kay?". Since the -v21
theme is simply providing an alternative definition of a theme defined elsewhere, dropping the -v21
theme will not break the build or break things at runtime, but merely will give us a Holo
-themed diagnostic activity.
I fail to see how this answer works with dependencies. I am also uncertain if it is complete, and it certainly does not appear to be supported. It also doesn't really qualify as "simple" — I would not expect somebody to try dropping this in a build.gradle
file just to block a single file from a diagnostic library like LeakCanary.
So, is there something simpler than this that works with now-current editions of the Android Plugin for Gradle?
EDIT:
Wrote advanced gradle task for you:
final List<String> exclusions = [];
Dependency.metaClass.exclude = { String[] currentExclusions ->
currentExclusions.each {
exclusions.add("${getGroup()}/${getName()}/${getVersion()}/${it}")
}
return thisObject
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile ('com.android.support:appcompat-v7:20.+')
debugCompile ('com.squareup.leakcanary:leakcanary-android:1.3.1')
.exclude("res/values-v21/values-v21.xml")
releaseCompile ('com.squareup.leakcanary:leakcanary-android-no-op:1.3.1')
}
tasks.create("excludeTask") << {
exclusions.each {
File file = file("${buildDir}/intermediates/exploded-aar/${it}")
println("Excluding file " + file)
if (file.exists()) {
file.delete();
}
}
}
tasks.whenTaskAdded({
if (it.name.matches(/^process.*Resources$/)) {
it.dependsOn excludeTask
}
})
Now you can use method .exclude()
on each dependency, providing into list of paths, you want to exclude from specified dependency.
Also, you can stack the .exclude()
method calls.
Try compileOnly keyword to mark the resource is used for compile only.
dependencies {
compileOnly fileTree(include: ['*.jar'], dir: 'libs')
}
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