March 9, 2017

How To Reduce Android APK Size

By Lalit Vasan


Android Application Size really matters when going live to the play store. Users often avoid downloading apps that seem too large, particularly in emerging markets where devices connect to often-spotty 2G and 3G networks or work on pay-by-the-byte plans.

I would like to share the few approaches which you can use to reduce apk size without impacting the quality of your app.

1. ProGuard

ProGuard is the most prominent enhancer for Java bytecode. It optimizes bytecode and removes unused instructions. It renames the classes, fields, and methods using short meaningless names which makes code safer from reverse engineering. It makes your Java and Android applications up to 90% littler and up to 20% quicker. You can learn more about proguard https://www.guardsquare.com/en/proguard.

To enable proguard:
Open build.gradle file in android studio and add minifyEnabled true and shrinkResources true.
But remember shrinking process of code slows down the time of build. So you should only use it when you are going to release your app or if you are giving it for testing.

build.gradle

android {
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                    'proguard-rules.pro'
        }
    }
    ...
}

minifyEnabled is responsible for shrinking your code files (e.g. Java). It is the main feature of ProGuard, and helps to shrink your APK as well as making it difficult to reverse engineer.

shrinkResources is used to remove unused resource files (such as images and other assets). For example, if you are compiling with an Android library, but you are not using some images in that Android library, they will not be included in the final build.

2. Vector Drawables

As the name implies, vector drawables are based on vector graphics, as opposed to raster graphics. It is similar to SVG file. In Android Vector Drawable are created with XML files. Before the Addition of Vector Drawable in Android SDK, developer had to create multiple version of images for different display resolutions . This take more time to create extra assets and consume more space that increases the Apk size.
Now there is no need to design different size image for mdpi, hdpi,xhdpi and etc. With Vector Drawable you need to create image only once as an xml file and you can scale it for all dpi and for different devices. This also not save space but also simplifies maintenance. You can learn how to create vector drawables http://www.androidtutorialshub.com/android-vector-drawable-example-using-appcompat-support-library/

3. Google Play Services

Select the compiling APIs extensively.
In versions of Google Play services prior to 6.5, you had to compile the entire package of APIs into your app. In some cases, doing so made it more difficult to keep the number of methods in your app (including framework APIs, library methods, and your own code) under the 65,536 limit.
From version 6.5, you can instead selectively compile Google Play service APIs into your app. For example, to include only the Google Map and Android Wear APIs, replace the following line in your build.gradle file:

compile 'com.google.android.gms:play-services:10.2.0'

with these lines:

compile 'com.google.android.gms:play-services-maps:10.2.0'
compile 'com.google.android.gms:play-services-wearable:10.2.0'

Here you can see explore more Api’s of Google Play Services :- https://developers.google.com/android/guides/setup

4. Apk splits

You often build a single APK to support all your target devices whenever possible, that might result in a very large APK due to files needed to support multiple screen densities or Application Binary Interfaces (ABIs). One way to reduce the size of your APK is to create multiple APKs that contain files for specific screen densities or ABIs. Gradle can create separate APKs that contain only code and resources specific to each density or ABI. To learn how to configure your build to generate multiple APKs follow this link https://developer.android.com/studio/build/configure-apk-splits.html

5. Optimize png images

A great way to improve the performance of your app is to optimize the size of your images. Smaller image sizes require less memory usage, disk space , load time and most important reduce Apk size. PNG images can be reduced in file size without losing quality. To do this, use a tool such as OptiPNG or PNGCrush. Both are great for reducing PNG file size while still ensuring image quality. You can also use some online image optimization service TinyPng





6. 9-patch images

A 9-patch png is a special format for PNG that can be used for backgrounds. Nine patch images are especially useful when designing buttons. Instead of defining a regular bitmap to be used as a background, a 9patch defines nine segments — for each of the four corners, the four edges, and the centre. To learn more about 9-patch image https://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch
and to learn how to draw 9-patch tool is a WYSIWYG editor included in Android Studio https://developer.android.com/studio/write/draw9patch.html

7. Recommended Media formats

Some times applications are heavily reliable on images, audio or video, so another way you can reduce the APK size is by using certain media formats. It is highly recommended that you use the following media formats for images, audio and video:
Images: PNG or JPEG. Use PNGs, since it is a lossless format it is very suitable for textures and artwork as there will be no visual artefacts from the compression. If there are space constraints, use JPEGs or a combination of PNGs and JPEGs. A high quality JPEG image may work fine for large photo-realistic images, which the JPEG compression scheme is optimised for.
Audio: AAC Audio is recommended for all audio resources. AAC achieves better compression at a given quality, compared to mp3 or Ogg Vorbis. Raw formats such as WAV should never be used. The common rational for using the WAV format is that decoding compressed audio streams usually means high latency at playback. However, Android provides the Sound Pool API which enables applications to use compressed audio streams without the penalty of high latency.
Video: Use H264 AVC. Encode the video to a resolution no larger than the screen resolution of the target device (if known).
Know more about Supported Media Formats by android https://developer.android.com/guide/topics/media/media-formats.html

8. Reuse Resources

Reusing stuff is probably one of the first important optimization you learn when starting developing on mobile. It will not even reduce your Apk size but also save your time to develop the same thing again and again.
For example You can include a separate resource for variations of an image, such as tinted, shaded, or rotated versions of the same image. But It is recommended, that you reuse the same set of resources and customize them as needed at runtime.
Android provides several utilities to change the color of an asset, either using the android:tint and tintMode attributes on Android 5.0 (API level 21) and higher. For lower versions of the platform, use the ColorFilter class.
The following code snippet provides an example of turning an “expand” arrow into a “collapse” arrow icon by simply rotating the original image 180 degrees:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_arrow_expand"
    android:fromDegrees="180"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toDegrees="180" />

9. Remove Debug Information

It is highly recommended that you remove all debug-related functionality from the application. The application generally does not see or use this data, and the Android operating system does not require it to run the application. Hence, the debug information only wastes space, and should be removed.

10. Lint tool

Proguard optimizes the java code only. Unfortunately, it doesn’t looks on the resources side. For Example if you have an image named icon_arrow.png in res/drawable and it is not used anywhere, Proguard only removes it’s reference in the R class but keeps the associated image in place.
The lint tool, a static code analyzer included in Android Studio, detects resources in your res/ folder that your code doesn’t reference. When the lint tool discovers a potentially unused resource in your project, it prints a message like the following example.

res/drawable/icon_arrow.png: Warning: The resource R.drawable.icon_arrow appears
    to be unused [UnusedResources]

These are small things and I am sure it won’t take much of your time to implement. But, in the end, you would end with a leaner app size and definitely a smile on your face. Please feel free to comment if you have newer techniques as well as ask questions. And, yeah! If this post helps you please do share!

Enjoy Coding and Share Knowledge