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)
Related
I just updated Android Studio to 3.5.
BTW updated the Gradle version and several libraries.
To my surprise, the application does not fit into a single DEX (uses over 73,500 methods, previously in debug version as far as I remember ~50K)
What changes have I made:
Kotlin 1.3.41 -> 1.3.50
classpath 'com.android.tools.build:gradle:3.5.0' from 3.4.2
classpath 'com.google.gms:google-services:4.3.1' from 4.3.0
implementation 'com.google.android.gms:play-services-ads:18.1.1' from 18.1.0
implementation 'com.google.firebase:firebase-core:17.1.0' from 17.0.1
The new release APK has fewer (60) methods (26760) than the previous one.
Other problem I got:
NDK Resolution Outcome: Project settings: Gradle model version=5.4.1, NDK version is UNKNOWN error
App using AndroidX.
app is compiling & work now OK when set
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
I imported settings from an older version of Android Studio. Maybe here is the problem?
Or there is no problem and I have to reconcile and use multiDEX (for development) and in release apk drop multiDEX?. Will multidex be better than minifyEnabled for debug version?
Changed:
debug {
// minifyEnabled true
// proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
multiDexEnabled true
}
And is working with multiDex when I run emulator with APK >=21.
Prior 21 API will test using release APK only.
BTW APK analyze my debug version show:
classes.dex 54806 methods
classes2.dex 1107 methods
classes3.dex 6725 methods
Total: 62638.
When I disable multiDex.
Cannot fit requested classes in a single dex file (# methods: 73883 > 65536) ;))
Something is not right ;)
set multiDexEnabled true globally or for both build-types - else the release build will exceed the 64k limit of a single DEX file. debug & release build can have different method count, because these are two merged source-sets - and unused classes may also be stripped (multiDexEnabled true also adds it's own library). While minifyEnabled true for debug builds is useless ...and I really don't understand why one would intend to do that. When the non-public class/method names in the APK do not match those class names in the IDE, one might find it difficult to debug that, because breakpoints will not catch; it's alike shooting oneself into the leg.
If a single library update introduces a new dependency, this can add lots of classes & methods.
I am trying to view APK contents using Android Studio's APK analyzer tool.
According to https://developer.android.com/studio/build/apk-analyzer, APK would contain dex files from which class information can be viewed.
With my sample application, I am able to see .java classes directly in the APK. Refer APK files.
I want to avoid having the JAVA classes as part of APK to reduce APK size and for security reasons.
Use like this in your build.gradle -
android {
buildTypes {
release {
// Enables code shrinking, obfuscation, and optimization for only
// your project's release build type.
minifyEnabled true
// Enables resource shrinking, which is performed by the
// Android Gradle plugin.
shrinkResources true
// Includes the default ProGuard rules files that are
packaged with
// the Android Gradle plugin. To learn more, go to the
section about
// R8 configuration files.
proguardFiles getDefaultProguardFile(
'proguard-android-optimize.txt'),
'proguard-rules.pro'
}
}
...
}
Do read google Docs for better understanding. You will get a clear picture.
Follow this -
https://developer.android.com/studio/build/shrink-code
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
Am developing android application with some confidential data.I need to obfuscate code.I have searched for a solution long time, still am not getting solution.
You have several ways of doing this. The one you can easily integrate inside your application is to use proguard rules and gradle.
Define your proguard-rules.pro with the specifications you see fit. Below there is a link which explains the usage of most of them
http://proguard.sourceforge.net/manual/usage.html
After that, in the build gradle of your top application module, in case you have a tree of dependencies, add:
BuildTypes{
release{
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
In this case, every time you run a release version of your application, it will run your proguard file configuration. Have in consideration that proguard does not obfuscate the name of the activities.
Use minifyEnabled true in your app level build.gradle
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'
}
}