A lot has been written about the monolithic nature of the Google Play Services and why it should be split into more libraries. For now the workaround to keep your APK small is to use proguard to strip out unused references. This works pretty well for classes.dex, but not for the included resources.
I get around 1 MB of additional unused resources and with a bundled Android Wear app this overhead doubles. So my APK is 2 MB larger than needed.
I'm wondering whether there is some straightforward way in Gradle to exclude some resources coming from the dependencies AARs from the resulting APK.
It seems that the AAPT options in the Gradle Android plugin only allow filtering assets.
I was thinking about hooking in some custom aapt script which would call remove for a list of resources using aapt before signing the APK for release.
Does someone else have a simpler solution?
After some research I found the following sub-optimal solution. I had to list all the not needed resources manually (luckily patterns are applicable) and make sure also to delete all files where they are referenced. Below is an example which makes my Wear app APK from 1.5 MB into 300kb and the APK is working normally without issues.
I had to create my own task stripResources
and hook it between standard Android plug-in tasks: mergeReleaseResources
and processReleaseResources
.
task stripResources << {
println "Custom resource stripping in: $buildDir"
delete fileTree(dir: "$buildDir", include: "**/layout/confirmation_activity_layout.xml")
delete fileTree(dir: "$buildDir", include: "**/layout/watch_card_content.xml")
delete fileTree(dir: "$buildDir", include: "**/common_signin*.png")
delete fileTree(dir: "$buildDir", include: "**/drawable/common_signin*.xml")
delete fileTree(dir: "$buildDir", include: "**/generic_confirmation*.png")
delete fileTree(dir: "$buildDir", include: "**/drawable/confirmation_*.xml")
delete fileTree(dir: "$buildDir", include: "**/drawable/card_background.xml")
delete fileTree(dir: "$buildDir", include: "**/card_frame*.png")
delete fileTree(dir: "$buildDir", include: "**/go_to*.png")
delete fileTree(dir: "$buildDir", include: "**/drawable/go_to_*.xml")
delete fileTree(dir: "$buildDir", include: "**/ic_plusone*.png")
delete fileTree(dir: "$buildDir", include: "**/powered_by_google*.png")
// if you only have English you can teh following to filter out some GPS texts wich also take few hundreds of kb
// delete fileTree(dir: "$buildDir", include: "**/values-*/values.xml")
}
tasks.whenTaskAdded { task ->
if (task.name == 'processReleaseManifest') {
task.dependsOn stripResources
}
}
You can do a similar task for regular Android APK.
As of version 0.14 of the Android Gradle plugin, this can be accomplished automatically as mentioned in this post:
android {
buildTypes {
release {
minifyEnabled true
shrinkResources true
}
}
}
shrinkResources
is a flag that tells the compiler to skip any resources that aren't referenced. minifyEnabled
is the new name for runProguard
, which must be enabled for shrinkResources
to work.
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