The most complete summary of APK slimming of Android performance optimization

640?wx_fmt=gif&wxfrom=5&wx_lazy=1&retryload=1

Hot Article Guide |  Click on the title to read

Android Architecture Advanced Learning Roadmap

so cool! 74 APP complete source code!

Welcome to Java and Android Architecture Knowledge Planet


By: I am a vampire

Link: https://www.jianshu.com/p/5921e9561f5f


With the gradual increase of business complexity, the code and resources are also increasing, and the size of your APP is also increasing. From the user level, in the face of tens of megabytes of APPs, you will still hesitate to download in the case of non-WIFI. If you don't download, you may lose a user. At the company level, traffic is money, and it is particularly important to reduce the size of the app. From the developer level, if you master this craft, it will be a bit overwhelming.

Without further ado, let's get down to business.

01 Those things about APK structure

If you know yourself and your enemy, you will be able to fight a hundred battles. It is helpful for us to understand the structure of an application APK. An APK file consists of a ZIP archive that contains all the files that make up the application. These files include Java class files, resource files, and files containing compiled resources.

The APK contains the following directories:

  • META-INF/: Contains the CERT.SF and CERT.RSA signature files and the MANIFEST.MF manifest file.

  • assets/: Contains application resources that the application can retrieve using the AssetManager object.

  • res/: Contains the uncompiled resource resources.arsc.

  • lib/: Contains compiled code specific to the processor software layer. This directory contains subdirectories for each platform, like armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, and mips.

  • resources.arsc: Contains compiled resources. This file contains the XML content of all configurations in the res/values/ folder. The packaging tool extracts this XML content, compiles it into binary format, and archives the content. This content includes language strings and styles, as well as content paths directly included in the resources.arsc file, such as layout files and images.

  • classes.dex: Contains classes compiled in a DEX file format understood by the Dalvik/ART virtual machine.

  • AndroidManifest.xml: Contains the core Android manifest file. This file lists the application's name, version, access rights, and referenced library files. The file uses Android's binary XML format.


Let's take a look at the file directory after the unzip of Taobao APP

640?wx_fmt=png


Generally speaking, the larger parts of the APK structure are files or directories such as classes.dex, lib, res, and assets. Therefore, the following four cases will be explained.


In addition, we can analyze APK through APK Analyser


640?wx_fmt=png


02 Decrease classes.dex

classes.dex contains all the Java code. When you compile your application, gradle will convert the .class files in all your modules into .dex files and combine these files into a classes.dex file.


A single classes.dex file can hold approximately 64K methods. If you reach this limit, you must enable multidexing in your project. This will create another classes1.dex file to store the remaining methods. So the number of classes.dex files depends on the number of your methods.


Reduce the use of third libraries


With the frequent changes of the business and the increase in complexity, we often use third-party Libaray. Sometimes we may only use a small part of the functions. At this time, we need to carefully consider the full reference. From my development experience, I would rather refer to my own implementation than introduce a third-party library.


avoid enumeration


An enumeration can add about 1.0 to 1.4 KB in size to your application's classes.dex file. These additions can quickly accumulate to complex systems or shared libraries. If possible, consider using the @IntDef annotation, this type conversion preserves all the type safety benefits of enums.


Using ProGuard


The following piece of code from the build.gradle file is used to enable code compression for release builds:


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


In addition to the minifyEnabled property, there is also the proguardFiles property for defining ProGuard rules:

getDefaultProguardFile('proguard-android.txt') 方法可从 Android SDK tools/proguard/ 文件夹获取默认的 ProGuard 设置。


提示:要想做进一步的代码压缩,请尝试使用位于同一位置的 proguard-android-optimize.txt 文件。它包括相同的 ProGuard 规则,但还包括其他在字节码一级(方法内和方法间)执行分析的优化,以进一步减小 APK 大小和帮助提高其运行速度。


proguard-rules.pro 文件用于添加自定义 ProGuard 规则。默认情况下,该文件位于模块根目录(build.gradle 文件旁)。


03 优化assets和res中的资源文件

题外话


res/raw和assets的相同点:


两者目录下的文件在打包后会原封不动的保存在apk包中,不会被编译成二进制。


res/raw和assets的不同点:


1. res/raw中的文件会被映射到R.java文件中,访问的时候直接使用资源ID即R.id.filename;assets文件夹下的文件不会被映射到R.java中,访问的时候需要AssetManager类。


2. res/raw不可以有目录结构,而assets则可以有目录结构,也就是assets目录下可以再建立文件夹。


针对不同的情况,对于资源文件有不同的优化策略。一般来讲,对于res/drawable-**ddpi中的png资源可以进行压缩。


图片资源优化策略


格式压缩


使用TinyPng或者Guetzli进行压缩。Guetzli的使用可以参见我之前写的博文在Mac上使用Google图片压缩工具Guetzli

https://www.jianshu.com/p/565e944bb594


使用WebP文件格式


定位Android 3.2(API级别13)或更高级别时 ,您也可以使用WebP文件格式来制作图像,而不是使用PNG或JPEG文件。WebP格式提供有损压缩(如JPEG)以及透明度(如PNG),但可以提供比JPEG或PNG更好的压缩。


Android 4.0 (API level 14) 支持有损压缩的WebP格式,Android 4.3 (API level 18) 开始支持无损透明WebP图像。


看下图:


640?wx_fmt=png

压缩效率极高,仅为PNG格式的12%。惊喜不惊喜。。。


使用矢量图形


您可以使用矢量图形来创建与分辨率无关的图标和其他可伸缩媒体。使用这些图形可以大大减少您的APK足迹。


矢量图像在Android中表示为VectorDrawable对象。通过一个VectorDrawable对象,一个100字节的文件可以生成一个与屏幕尺寸一致的清晰图像。


但是,系统渲染每个 VectorDrawable对象需要很长时间,而较大的图像需要更长的时间才能显示在屏幕上。因此,只有在显示小图像时才考虑使用这些矢量图形。


其它策略


有时候我们可能对一张图片进行重复利用,比如一张图片仅仅是整体颜色的变换可以使用setColorFilter或者tint。尽量减少使用帧动画,那可是一堆图片呀。


压缩资源


要启用资源压缩,请在 build.gradle 文件中将 shrinkResources 属性设置为 true。


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


资源压缩器目前不会移除 values/ 文件夹中定义的资源(例如字符串、尺寸、样式和颜色)。这是因为 Android 资源打包工具 (AAPT) 不允许 Gradle 插件为资源指定预定义版本。


同时,我们也可以指定哪些资源可以保留下来。

例如,将下边的代码保存在 res/raw/keep.xml。构建不会将该文件打包到 APK 之中。

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
   tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"
   tools:discard="@layout/unused2" />


resources有以下属性:

tools:keep 指出哪些资源会保留
tools:discard 指定哪些资源需要剔除
tools:shrinkMode 资源压缩模式,有两种取值strictsafe,默认为safe


safe和strict的优化策略:


safe可以简单理解为安全模式,它会尽最大努力检查代码中可能会使用到的资源进行保留,避免运行时错误。


如果你的代码调用Resources.getIdentifier(),这就表示你的代码将根据动态生成的字符串查询资源名称。当你执行这一调用时,默认情况下资源压缩器会采取防御性行为,将所有具有匹配名称格式的资源标记为可能已使用,无法移除。


String name = String.format("img_%1d", angle + 1);
res = getResources().getIdentifier(name, "drawable", getPackageName());


img_ 前缀的资源标记为已使用。


在strict模式下,img_前缀的资源会做未使用的处理,因此你需要使用tools:keep手动进行已使用标识。


移除未使用的备用资源


我们知道google给我们的apk提供了国际化支持,如适应不同的屏幕分辨率的drawable资源,还有适应不同语言的字符串资源等等,但是在很多情况下我们只需要一些指定分辨率和语言的资源就可以了,这个时候我们可以使用resConfigs方法来配置。


 
  

defaultConfig {
   // 对于国际化支持只打包中文资源,
   resConfigs "zh-rCN"
}


04 lib中资源优化

这里我们主要讲一下lib中动态链接库的优化策略,也就是SO文件。如果你有NDK的开发经验可能会更容易理解一些。


为了支持不同指令集的情况,应用可能会包含armeabi、armeabi-v7a、x86的SO文件等。

目前主流的机型都是支持armeabi-v7a的,并且armeabi-v7a兼容armeabi。所以在一般的开发中我们只需要使用armeabi-v7a 进行ABI支持。


有些SO库可以采用网络下载,把负担放到用户安装完应用之后。对于哪些SO文件可以放到网络中加载,还需要看具体业务情况。


题外话,如果运行时找不到SO的话,会导致应用崩溃。

java.lang.UnsatisfiedLinkError: Couldn't load stlport_shared from loader dalvik.system.PathClassLoader: findLibrary returned null
at java.lang.Runtime.loadLibrary(Runtime.java:365)
at java.lang.System.loadLibrary(System.java:535)
at com.your.app.NativeClass.<clinit>(Native.java:16)
... 63 more
Caused by: java.lang.UnsatisfiedLinkError: Library stlport_shared not found
at java.lang.Runtime.loadLibrary(Runtime.java:461)
at java.lang.System.loadLibrary(System.java:557)
at com.your.app.NativeClass.<clinit>(Native.java:16)
... 5 more


我们也是有办法应对的,可以参见这个开源项目ReLinker

https://github.com/KeepSafe/ReLinker


In addition, I will talk about the optimization of SO separately.

If you have a good article that you want to share with you, you are welcome to contribute, just send me the article link directly


Finally, everyone is welcome to join our knowledge planet. The second phase is in full swing, and nearly 1,000 people have joined the study :

Everyone is welcome to join as soon as possible. This period ends on March 10, 2019, so the sooner you join, the better. The promotion ends. The current entry fee has been raised from 79 yuan to 89 yuan, and the fee will increase by 10 yuan for every 100 people in the future~

640?wx_fmt=jpeg

Scan WeChat or click the QR code above to get Android\Python\AI\Java and other advanced resources

For more learning materials, click "Read the original text " below

640?wx_fmt=gif

Guess you like

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