Slimming APKs with Gradle

Introduction: The size of APK files has grown dramatically over the past few years. In general, the reasons are as follows: Android developers acquire more dependencies, add more density, and Apps add more functionality. But in practice we should keep APKs as small as possible. Smaller APKs mean that users can download and install apps faster, and make them take up less memory. 
This article, from Gradle for Android Chinese Edition, will examine how to set several properties in the Gradle build configuration file to shrink the APK file.

ProGuard

  ProGuard is a Java tool that not only reduces APK file size, but also optimizes, obfuscates and pre-verifies your code at compile time. It goes through all the code paths of your app to find unused code and delete it. 
  ProGuard also renames your classes and fields. This process will preserve traces of the application, making it more difficult for decompilers to understand the code. 
  In Gradle's Android plugin, under its build type there is a boolean property called minifyEnabled that you need to set to true to activate ProGuard:

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

  When minifyEnabled is set to true, during the build process, the proguardRelease task is executed and ProGuard is called. 
  After activating ProGuard, you should retest the entire application, as ProGuard may remove some code you still need to use. This is why many developers dislike ProGuard. To solve this problem, you can define ProGuard rules to exclude those classes that are removed or obfuscated. We can use the proguardFiles property to define files that contain ProGuard rules. For example, to keep a class, you can add a simple rule like this:

-keep public class <MyClass>

  The getDefaultProguardFile('proguard-android.txt') method gets the default ProGuard settings from the proguard-android.txt file in the tools/proguard folder of the Android SDK. 
  In Android Studio, the proguard-rules.pro file is added by default to new Android modules, so you can simply add some rules for that module in this file.

Tip: Every application or dependent library you build has different ProGuard rules, so we won't go into more detail in this book. If you want to know more about ProGuard and ProGuard rules, you can refer to the official documentation of AndroidProGuard at http://developer.android.com/tools/help/proguard.html . In addition to shrinking Java code, you can also shrink used resources.

Reduce resources

  When packaging an app, Gradle and the Android plugin for Gradle can remove all unused resources during the build. This feature can be very useful if you have old resources that you forgot to delete. Another use case is when you import a dependency library that has many resources and you only use a small part of it, you can solve this problem by activating minify resources. There are two ways to reduce resources: automatic and manual.

auto-reduce

  The easiest way is to set the shrinkResources property in your build. If you set this property to true, the Android build tools will automatically determine which resources are not being used and exclude them from the APK. One requirement to use this feature is that ProGuard must be started at the same time. This is because the way minified resources work is that the Android build tools cannot figure out which resources are not being used until code references to those resources are removed. 
  The following code snippet shows how to configure automatic resource reduction in a build type:

android {
       buildTypes {
       release {
             minifyEnabled = true
             shrinkResources = true
             }
       }
}

  如果你想看看在激活了自动化资源缩减之后,APK 缩减了多少,则可以运行shrink-ReleaseResources 任务。该任务会打印出包的大小缩小了多少:

:app:shrinkReleaseResources
Removed unused resources: Binary resource data reduced from 433KB
to 354KB: Removed 18%

  你可以通过在构建命令中添加 –info 标志,来获得APK 缩减资源的概览:

$ gradlew clean assembleRelease –nfo

  当你使用该标志时,Gradle 会打印出许多关于构建过程的额外信息,包括最终构建不会输出的每个资源。 
  自动资源缩减有一个问题,即它可能移除了过多的资源,特别是那些被动态使用的资源可能被意外删除。为了防止这种情况的发生,你可以在res/raw/ 下的一个叫作keep.xml的文件中定义这些例外。一个简单的keep.xml 文件如下所示:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:keep="@layout/keep_me,@layout/also_used_*"/>

  keep.xml 文件自身也将从最终的结果中被剥离出来。

手动缩减

  去除某种语言文件或某个密度的图片,是删减资源的一种比较好的方式。一些依赖库,例如Google Play Services,其包含了多种语言。如果你的应用只支持一两种语言,那么在最终的APK 中,包含所有语言的文件就会浪费许多资源。这时你就可以使用resConfigs 属性来配置你想保留的资源,将其余部分删除。 
  如果你只想保留英语、丹麦语和荷兰语的字符串,则可以这样使用resConfigs :

android {
    defaultConfig {
          resConfigs “en", “da", “nl"
    }
}

  你也可以这样处理密度集合:

android {
    defaultConfig {
          resConfigs “hdpi", “xhdpi", “xxhdpi", “xxxhdpi"
    }
}

  你甚至可以结合语言和密度。实际上,使用此属性可以限制每一种类型的资源。 
  如果设置ProGuard 让你感觉很困难,或者你仅仅想在应用中去除不支持的语言资源或密度,那么你可以使用resConfigs 来缩减资源。 
  本文选自《Gradle for Android 中文版》,点此链接可在博文视点官网查看。 
                   图片描述

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326399325&siteId=291194637
Recommended