__ _ __
___ ____ ___/ /______ (_)__/ /
/ _ `/ _ \/ _ / __/ _ \/ / _ /
\_,_/_//_/\_,_/_/ \___/_/\_,_/
resource cleanup
Android Studio has a built in option for removing unused resources. Unfortunately, it has some bugs. In trying to find an alternative, I found android-resource-cleaner which does what I wanted. Unfortunately, it hasn't been updated in a fewa years, and considering that Python 2 is now deprecated and no longer comes install on OS X, I made my own version based on the aforementioned project.
- support for Python 3
- use ripgrep instead of
grep. - use xmlstarlet instead of
sedto not break json in edge cases. - added a script for removing unused colors.
- support for webp in drawable cleanup.
- added support for ignoring lint baselines.
All these scripts work in pretty much the same way - given a list of files or a folder, they search for resource references (by means of @[resourceType] or R.resourceType references) for the resource. If not found, the resource is removed.
There are some important limitations:
- dynamically loaded resources (i.e. looking them up by name at runtime via
getIdentifier, etc) will likely be detected as "unused" even if they are used. This is because there's no easy way to figure out that they're in use, since they're not actually referencing anRtype directly, and instead, the resource name is constructed from a string at runtime. - resource references looking like
layout.foo(where theimportstatement importsR.layoutinstead ofR) may be detected as unused, despite being in use. This is not difficult to work around, however.
- Python 3 - no extra modules or packages necessary.
- ripgrep - it's very fast and has some nice features over grep. on macOS,
brew install ripgrep. - fd - a really nice faster find tool. on macOS,
brew install fd. - xmlstarlet - this is for properly updating xml without breaking it. on macOS,
brew install xmlstarlet.
Most of these are run in the same way - use something like fd to find each file of the corresponding type (for colors, dimens, and strings) and pass them in to their corresponding scripts. For drawable and layout resources, the directories are passed in instead.
Pass the set of layout directories to clean_layouts script, one by one:
for i in `fd -p 'src/main/res/layout' -td`; do
python3 clean_layouts.py $i/
donePass the set of res directories to clean_drawable script, one by one:
for i in `fd res -td | rg src/main/res`; do
python3 clean_drawable.py $i/
donePass each main strings.xml to the clean_strings script. It will take care of removing the corresponding language translations for any strings it removes.
for i in `fd -p 'main/res/values/strings.xml'`; do
python3 clean_strings.py $i
donePass each dimens.xml file to clean_dimens script, one by one.
for i in `fd dimens.xml`; do
python3 clean_dimens.py $i
donePass each colors.xml to clean_colors script, one by one.
for i in `fd colors.xml`; do
python3 clean_colors.py $i
done