I'm using AppCompat support library in my Android project. AppCompat has plenty of drawables and resources which I don't use in my app. That unnecessary files increases my 900K app to above 2M, which I don't like.
Is there any way to exclude those files when creating the APK file? Or I should obfuscate the library in my code instead of making a dependency?
I'm using Gradle in Android Studio.
Thanks
EDIT 1 I am using proguard already. but proguard can't know I don't want to have drawable-xxxhdpi or values-it for example.
EDIT 2 I am also using Android Lint, which can't help me, beacuse I don't access to lib's code directly, and android adds them when building the APK file.
Starting from version 24.2.0, the v4 Support Library has been split into several smaller modules.
So, apart from using shrinkResources and proguardFiles, also make sure that you are using only the specific modules that your app needs. e.g.
If your app only uses Compat utils like NotificationCompat, ContextCompat or ResourcesCompat etc., use only the compat module as:
compile 'com.android.support:support-compat:24.2.0'
From Android Gradle Build System, since version 0.7.0:
New option on product Flavor (and defaultConfig) allow filtering of resources through the -c option of aapt
You can pass single value (resConfig) or multiple values (resConfigs) through the DSL.
All values from the default config and flavors get combined and passed to aapt.
See "basic" sample.
In the "basic" sample:
defaultConfig {
...
resConfig "en"
resConfigs "nodpi", "hdpi"
}
So, try the following to achieve what you asked for:
productFlavors {
...
frOnly {
resConfig "fr"
}
...
}
Note that you might also want to include *dpi, port, land, etc.. as well.
Answer is from: Android Studio exports strings from support library to APK, thanks to Primoz990
shrinkResources can also be an option for you. It is available since 0.14 - but be careful - it still has some pits like protect resources when using shrinkResources
Although OP has cleared up that he is using proguard, I would like to post some code if it helps someone because I am able to shrink my app from 3.8 MB to 3.1 MB using the accepted answer and further to mere 1.8 MB through proguard. I used this configuration in my app level build.gradle file:
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
Related
I have created a Wear OS module in our existing Android mobile application. Both application modules remain in the project like following:
Project/app
Project/wear/wear_presentation
Project/otherLibModule/other_lib_module_presentation
and we have a common.gradle that is used by app and wear_presentation:
buildTypes {
release {
minifyEnabled true
debuggable false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
debuggable true
minifyEnabled false
}
}
Before Wear OS module, we had a single proguard file inside app module that handles all minifying work, but now we have 2 application modules that have separate proguard files. That forces me to copy/paste all content from app proguard file into wear_presentation proguard file and this approach seems amateurish.
I want to use a single common proguard file that is used by both app and wear_presentation modules.
Is it possible?
Importing from Libraries is supported already.
https://developer.android.com/studio/build/shrink-code#configuration-files
/proguard.txt - If an AAR library is published with its own ProGuard rules file, and you include that AAR as a compile-time dependency, R8 automatically applies its rules when compiling your project.
Using rules files that are packaged with AAR libraries is useful if certain keep rules are required for the library to function properly—that is, the library developer has performed the troubleshooting steps for you.
However, you should be aware that, because ProGuard rules are additive, certain rules that an AAR library dependency includes cannot be removed and might impact the compilation of other parts of your app. For example, if a library includes a rule to disable code optimizations, that rule disables optimizations for your entire project.
/META-INF/proguard/ - for JAR libraries
It's commonly used by libraries like OkHttp https://github.com/square/okhttp/blob/okhttp_4.10.x/okhttp/src/main/resources/META-INF/proguard/okhttp3.pro
I have a complicated build setup for an android app which basically consists of a normal android app fused together with a Xamarin/Mono project in order to include an important C# library (like this: https://github.com/royd/KotlinAppWithXamarinDependency)
Everything is working fine except if I enable minification in my app/build.gradle via minifyEnabled true the app instantly crashes on startup because the Mono-runtime can't find native assemblies that are definitely contained in the apk.
This is the message I get in Logcat:
A/monodroid: No assemblies found in '(null)' or '<unavailable>'. Assuming this is part of Fast Deployment. Exiting...
With minifyEnabled false everything is working fine so I tried disabling all config options in my proguard-rules.pro:
-dontobfuscate
-dontoptimize
-dontshrink
And I also added the following lines to my app/build.gradle
packagingOptions {
doNotStrip "*/armeabi/*.so"
doNotStrip "*/armeabi-v7a/*.so"
doNotStrip "*/x86/*.so"
}
Unfortunately all this doesn't help.
I also decompiled a working and a broken apk with dex2jar to compare the bytecode. It seems to be exactly the same except for some enum-optimizations that shouldn't matter.
According to the error message in Logcat the error seems to be thrown from the native library libmonodroid.so.
So my question: What does minifyenabled flag do when all these config options are disabled?
Edit:
I have found out that minification works as intended when I use version 4.0.1 of Android Gradle Plugin (from July 2020). Upgrading the version to 4.1.0 (August 2020) breaks my app. Now the question is what changed between these two versions?
When you set the minifyenabled as true. The r8 will choose the configuration files but not only the proguard-rules.pro and the app/build.gradle to shrink, obfuscate, and optimize your app.
There are some others files such as AAR libraries: <library-dir>/proguard.txt and
JAR libraries: <library-dir>/META-INF/proguard/ and so on. So this error may be caused by the native library losing when you set the set the minifyenabled as true.
If you need more information, please check the official document:https://developer.android.com/studio/build/shrink-code#enable
In addition, you can check the 'proguard-android-optimize.txt' and when you add the -dontoptimize to proguard-rules.pro may cause a conflict.
I found out, that in the Android Gradle Plugin versions 3.6.0 to 4.1.0 they switched to a more performant tool for building apks called zipflinger.
This tool can be disabled by adding this line to my gradle.properties:
android.useNewApkCreator=false
When building the apk zipflinger stores the external .NET assemblies as DEFLATED zip entries instead of STORED and thats why monodroid cant read them.
References:
https://github.com/xamarin/xamarin-android/issues/6838#issuecomment-1110816027
https://copyfuture.com/blogs-details/20210119115509664T
I'm working on an Android SDK that is about to be split into separate modules, with some code being shared between others, namely:
shared classes
SDK with feature #1
SDK with feature #2
There is a need of obfuscating the output AARs. With one single module it's not an issue, but I can't find how to configure the whole project correctly with Proguard.
How does the Proguard obfuscation work in case when I want to publish a new version of all these libraries? Will all the modules be obfuscated separately? How can I make sure that all the modules will be obfuscated at once and the release version of the libraries will correctly refer to all the artifacts that are located in the shared module?
Not sure I understand the issue.
But if you want to release 2 SDKs now instead of 1 (before split), I don't think the setup should differ very much.
Just make sure you have proguard file in these SDKs and you are using it in the build script specific to that SDK (module). Then just run something like :sdk:assembleRelease and you are done.
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'library.pro'
}
It is described in detail in this issue:
Obfuscating the .aar files
I understand that shared module is not published, so there you just need to define specific proguard rules that will be used by other modules, like this:
release {
minifyEnabled true
consumerProguardFiles 'onboarding-proguard-rules.pro'
}
My assets and drawable are only 2mb java and xml sources is only 1mb but after build project the apk size is 20mb!
I set shrinkResources true
and remove unused resources and generate app with proguard.
Is there a way to reduce the size of apk?
Android Studio has its own apk analyzer which is very useful for cases like yours.
Analyze your apk file and check which files are using this much space.
https://developer.android.com/studio/build/apk-analyzer.html
Also using ProGuard helps to reduce apk size.
Additionally, avoid using unnecessary libraries. For example,
if you need to use Google Analytics, import gradle only analytics library like this:
compile 'com.google.android.gms:play-services-analytics:10.2.4'
do not use like this:
compile 'com.google.android.gms:play-services:10.2.4'
second example uses too much space and redundant classes and files.
at your gradle, normally debug apk will be larger than release APK about 50%. If you care about the debug size, just do the same config like release on debug config
buildTypes {
release {
minifyEnabled true <-- minify your code
shrinkResources true <-- remove any unused resources
zipAlignEnabled true <-- optimization
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' <-- enable proguard is important to shrink byte code
}
}
Second, if you are using google services dependencies, please use individual dependencies.. refer here In android studio 2.2 and above they have added apk analyser tool in Build menu. Use that to analyse APK.
Not only for google services, others library also. some library put android design or appcompat in their library. so you need to exclude those module (if you already have in your dependencies)
According to the "Resource Shrinking" webpage of Andriod documentations (here), you can minimize the app's size via the build.gradle file, by using these lines:
android {
...
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
You can do following things
Remove non required libraries. even use required libraries (like map
or gcm individual instead of full play service library)
Use vector images instead of multiple png.
Use zipAlignEnabled command in build file
Check my blog Different ways to reduce apk size
Main Points are :
android.enableR8=true // enable New R8 Code Shrinker
minifyEnabled true && Add Proguard Rules
Examine Your APK Using Android Studio’s APK Analyzer
Enable Resource Shrinking
Convert Your PNGs, JPEGs, and BMPs Into WebP
Avoid enumerations and use #IntDef annotation
Use aaptOptions { cruncherEnabled = false } to compress images
Use Remove Unused Resources android studio built-in function to remove all the unused resources in the application
Use Code Cleanup android studio built-in function to remove
Note: Go enable it! (*just double and triple check everything works afterwards)
In a big project while former developers already worked on, you can find dependencies in gradle that doesn't have any usages at all.
Do those dependencies affect apk size? and how dependencies affect apk size, what if you're just using one method from a library, does this mean that all the library files attached to your apk.
Yes, unused dependencies do increase the apk size.
Enabling
minifyEnabled true
can analyze all the bytecode and remove unused classes and methods.
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
shrinkResources true
}
}
It is good to remove all the unused dependencies from gradle
Do those dependencies affect apk size? and how dependencies affect apk size
Yes of course.
The dependencies are added in the final apk, so the classes and the resources are added and they increase the size of the apk.
what if you're just using one method from a library, does this mean that all the library files attached to your apk.
Yes, all the library is attached.
There are some features in gradle to add a dependency removing the unused resources.
Yes gradle dependency definitely affects your apk size. if you are not using gradle dependency anywhere in the project then please remove the dependency
And even if you are using one mehtod from a library all files are attached to your apk. so to avoid this enable proguard tool with shrinkResource as true. This will obfuscate and simply remove unused method in the library and reduce the apk size