A gradle plugin to remove unused android resources by Android Lint results xml file.
This is useful for CI because that is provided by gradle task.
Refactor > Remove Unused Resources...
action.-<qualifier>
: ex, values-night, drawable-hdpi, values-v26...)&#{unicode};
, don't replace >
with >
, don't replace XML empty
tag...Apply the plugin to your app module.
app/build.gradle.kts
plugins {
id("io.github.irgaly.remove-unused-resources") version "2.2.0"
}
Ensure your lint option is correctly set for UnusedResources
rule.
checkGeneratedSources = true
is required, if you use code generation such as DataBinding or
Epoxy.
checkDependencies = true
is required, if you use multi module project.
app/build.gradle.kts
android {
...
lint {
// checkGeneratedSources is slow down Android Lint analysing.
// It is recommended to disable this when you analyse other lint rules.
checkGeneratedSources = true
// checkDependencies = true : checkDependencies is true by default
}
}
othermodule/build.gradle.kts
android {
...
lint {
// if a module uses code generation, this is required each project.
checkGeneratedSources = true
}
}
Run Android Lint, that contains UnusedResources
analyser.
% ./gradlew :app:lintDebug
Run clean up task, then unused resources are deleted.
There are removeUnusedResources{variant}
tasks.
% ./gradlew :app:removeUnusedResourcesDebug
console outputs like:
> Task :app:removeUnusedResourcesDebug
> report from: .../app/src/main/res/values/colors.xml
delete resource element: R.color.black
delete resource element: R.color.unused_color
delete resource element: R.color.unused_color_with_night_theme
...
modified XML exmaple:
Only modifies unused resource tag, preserve others (XML indent, spaces, special reference characters...) as it is.
--- a/sample/src/main/res/values/strings.xml
+++ b/sample/src/main/res/values/strings.xml
@@ -1,7 +1,6 @@
<!-- header comment -->
<resources>
<string name="app_name">Plugin Sample</string>
- <string name="unused_string">unused</string>
<string name="empty1" />
<string name="empty2"></string>
<string name="character_reference">© = ©</string>
UnusedResources
ruleThis plugin provides simple utility for lint, that overrides lint options.
For example, this command let lint to check only UnusedResources
rule.
% ./gradlew :app:lintDebug -Prur.lint.onlyUnusedResources
The -Prur.lint.onlyUnusedResources
overrides lint options by settings below:
android {
lint {
// These settings are applied automatically by the plugin, when -Prur.lint.onlyUnusedResources is specified,
// so you don't have to add these settings in build.gradle.kts.
xmlReport = true // only app project
checkDependencies = true // only app project
checkGeneratedSources = true
checkOnly.clear()
checkOnly.add("UnusedResources")
warning.add("UnusedResources")
}
}
You can overrides a single lintConfig file for all projects.
% ./gradlew :app:lintDebug -Prur.lint.overrideLintConfig="./lint.unusedresources.xml"
The details of lint.xml format is here .
This is an example for CI usage.
% ./gradlew :app:lintDebug -Prur.lint.onlyUnusedResources
% ./gradlew :app:removeUnusedResourcesDebug
This executes:
checkOnly.add("UnusedResources")
.
app/build/reports/lint-results-debug.xml
.app/build/reports/lint-results-debug.xml
)There are options to set exclude resource ID rules or file path rules.
See Gradle configuration syntax section.
Gradle tasks:
task | description |
---|---|
removeUnusedResources{variant} | delete unused resources by {buildDir}/reports/lint-results-{variant}.xml |
removeUnusedResources | delete unused resources by {buildDir}/reports/lint-results-{default variant}.xml |
Gradle properties:
property | description | example |
---|---|---|
rur.dryRun | only output result, without deletion | ./gradlew :app:removeUnusedResourcesDebug -Prur.dryRun |
rur.lintResultXml | the lint result xml path from rootProject (or full absolute path). this option is only for removeUnusedResources task, it's ignored by removeUnusedResources{variant} task. |
./gradlew :app:removeUnusedResources -Prur.lintResultXml="./app/build/reports/lint-results-debug.xml" |
rur.lint.onlyUnusedResources | override lint option for checkOnly UnusedResources | ./gradlew :app:lintDebug -Prur.lint.onlyUnusedResources |
rur.lint.overrideLintConfig | override lint.lintConfig. the path is relative path from rootProject (or full absolute path) | ./gradlew :app:lintDebug -Prur.lint.overrideLintConfig="./lint.unusedresources.xml" |
Gradle configuration syntax is also available.
app/build.gradle.kts
removeUnusedResources {
// for dry run
// default: false
dryRun = true
// specify lint result xml directly
// this option is only for `removeUnusedResources` task, it's ignored by `removeUnusedResources{variant}` task.
// default: {buildDir}/reports/lint-results-{default variant}.xml)
lintResultXml = file("$buildDir/reports/lint-results-debug.xml")
// exclude resource Id list. match rule: entire match
excludeIds.add("R.color.unused_exclude_color")
// regular expression exclude resource Id list. match rule: regular expression entire match
excludeIdPatterns.add("R\\..*exclude_pattern.*")
// glob expression exclude file.
// file path is relative path from Project's root directory
excludeFilePatterns.add("**/values/exclude_colors.xml")
}
The details of glob pattern is documented in JDK FileSystem#getPathMatcher
This error is occurred with running Gradle on JVM 11. Running Gradle on JVM 17 will solve this error.
...
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring project ':sample'.
> Could not resolve all files for configuration ':sample:classpath'.
> Could not resolve io.github.irgaly.remove-unused-resources:plugin:1.4.1.
Required by:
project :sample > io.github.irgaly.remove-unused-resources:io.github.irgaly.remove-unused-resources.gradle.plugin:1.4.1
> No matching variant of io.github.irgaly.remove-unused-resources:plugin:1.4.1 was found. The consumer was configured to find a runtime of a library compatible with Java 11, packaged as a jar, and its dependencies declared externally, as well as attribute 'org.gradle.plugin.api-version' with value '7.4' but:
- Variant 'apiElements' capability io.github.irgaly.remove-unused-resources:plugin:1.4.1 declares a library, packaged as a jar, and its dependencies declared externally:
- Incompatible because this component declares an API of a component compatible with Java 17 and the consumer needed a runtime of a component compatible with Java 11
- Other compatible attribute:
- Doesn't say anything about org.gradle.plugin.api-version (required '7.4')
- Variant 'javadocElements' capability io.github.irgaly.remove-unused-resources:plugin:1.4.1 declares a runtime of a component, and its dependencies declared externally:
- Incompatible because this component declares documentation and the consumer needed a library
- Other compatible attributes:
- Doesn't say anything about its target Java version (required compatibility with Java 11)
- Doesn't say anything about its elements (required them packaged as a jar)
- Doesn't say anything about org.gradle.plugin.api-version (required '7.4')
- Variant 'runtimeElements' capability io.github.irgaly.remove-unused-resources:plugin:1.4.1 declares a runtime of a library, packaged as a jar, and its dependencies declared externally:
- Incompatible because this component declares a component compatible with Java 17 and the consumer needed a component compatible with Java 11
- Other compatible attribute:
- Doesn't say anything about org.gradle.plugin.api-version (required '7.4')
- Variant 'sourcesElements' capability io.github.irgaly.remove-unused-resources:plugin:1.4.1 declares a runtime of a component, and its dependencies declared externally:
- Incompatible because this component declares documentation and the consumer needed a library
- Other compatible attributes:
- Doesn't say anything about its target Java version (required compatibility with Java 11)
- Doesn't say anything about its elements (required them packaged as a jar)
- Doesn't say anything about org.gradle.plugin.api-version (required '7.4')
...