The Gradle build system for Android supports "resource shrinking": the automatic removal of resources that are unused, at build time, in the packaged app. In addition to removing resources in your project that are not actually needed at runtime, this also removes resources from libraries you are depending on if they are not actually needed by your application. For example, your application is using Google Play Services to for example access Google Drive functionality, and you are not currently using Google Sign In, then this would remove the various drawable assets for the Sign In buttons.
Note that resource shrinking only works in conjunction with code shrinking (such as ProGuard). That's how it can remove unused resources from libraries; normally, all resources in a library are used, and it is only when we remove unused code that it becomes apparent which resources are referenced from the remaining code.
To enable resource shrinking, update your build type as follows:
Again, you have to enable
When you enable
If you want to see which resources are actually removed, you can supply the
You can tell the build system about resources you want to keep with the special
The value of the keep attribute can be a comma separated list of resource references to keep, and they can also use the asterisk character as wildcards. Example:
You can also specify tools:discard to deliberately remove resources that were kept:
Normally, the build system can accurately determine whether a resource is used or not. However, if your application makes a call to
so based on the above code fragment the build system will deliberately mark all resources with the prefix
It's possible that your code will contain many strings that are overly broad. You can optionally turn off this "better safe than sorry" handling, and ask for the resource shrinker to only consider resources referenced if it's certain. In that case it will be up to you to manually keep resources that you are referencing at runtime. This is similar to how code shrinking already works; you have to provide a proguard configuration file where any classes referenced by reflection are explicitly kept.
To turn off the safety checks, set the shrinkMode to "strict" as in the following keep.xml file:
To track down problems with resource shrinking (such as "why did resource X get removed?" or "why didn't resource Y get removed?"), you can use the
For example, let's say I want to know why @drawable/ic_plus_anim_016 is still in my APK:
In the build output resource reference graph, I find that it's referenced from a different resource:
Therefore, I now need to know why
If we are not using strict checking, resource id's can be marked as reachable if there are string constants which look like they may be used to construct resource names for resources loaded dynamically. In that case, if you search the build output for the resource name you may find a message like this:
If you see one of these strings, and you are certain that the String is not being used to load the given resource dynamically, you can use the
(There are some additional details on how to diagnose resource shrinking in this bug report: https://code.google.com/p/android/issues/detail?id=80872.)
In addition to looking for calls to Resources#getIdentifier, the build system will also look through all the String constants in your code, as well as various
In addition to removing unused resources, you can also use the Android Gradle plugin's "resConfigs" feature to have it remove any resource configurations that you app does not need.
For example, let's say the messages in your application have not been translated and are all in English. If you are using a library such as Google Play Services, you are picking up translations for all of the messages in those libraries. When functionality in the library is accessed, those will be shown to the user. Whether you prefer that, or want to have the whole app use a single language, is up to you. But if you choose to have a single language, or more generally, just the languages your app is targeting, you can set that up in your build.gradle file, and then at build time all other languages are dropped (which will make your APK smaller, similar to the resource shrinking facility).
Here's what you add to your build.gradle file if you for example want to limit your languages to just English and French:
You could also add