減少apk大小

前言

apk的大小對於下載apk應用的用戶多少有直接的影響,由於手機內存的限制和網絡環境的限制,同一個應用隨着apk越大下載的和使用的人數就會越少,所以減少apk的大小是非常重要的。本文從apk編譯過程,apk的組成,apk大小減少的方法三個方面分析如何減少apk的大小

1、apk的編譯過程

在構建過程中,Android項目會被編譯,打包,生成.apk文件,apk文件包含了運行的全部必要信息。主要包括:
1、.dex文件

2、AndroidManifest.xml文件

3、編譯的資源文件resources.arsc

4、未編譯的資源文件

Android編譯打包簡單流程圖


在這裏插入圖片描述
上面的流程圖中簡單的概括了Android編譯和打包過程,Android項目編譯和打包生成apk文件,apk文件簽名後,使用adb工具安裝在Android device或者emulator上就可以運行了。

Android 具體的build過程

.apk文件要通過打包過程中許多工具生成中間文件最終生成的。

apk打包工具

在這裏插入圖片描述
由上圖看出Android 構建過程中包括的構建工具有:

aapt(The Android Asset Packaging Tool ):aapt Android中的資源打包工具,主要是用於處理Android項目中的資源文件比如xml,drawable,等文件。

Java compiler: java編譯器,編譯java文件生成.class文件。

dex: dex生成器,dex會把class轉化爲Dalvik byte code,也會把第三方的源碼編譯進.dex文件中。

apkbuilder: apk生成器,編譯過的資源文件和未編譯的資源文件以及dex文件還有其他文件通過apk builder生成apk文件

jarsigner: 簽名器,.apk文件通過簽名後生成signed.apk文件,簽名後的apk就可以安裝和運行了。

apk的build流程圖

在這裏插入圖片描述
上面的流程圖可以很清晰的看到打包整個打包的過程:

1、資源打包過程

首先項目中資源文件通過aapt資源打包工具生成R.java文件,和編譯過的資源文件resources.arsc,R.java文件中存放的是各個資源的id,在java代碼中通過R文件中的id來找到對應的資源。resources.arsc中放的是編譯過的資源文件相關的信息:比如xml文件的節點(LinearLayout, RelativeLayout)佈局的屬性( android:layout_width)資源的id。下圖是資源打包更具體的流程:

在這裏插入圖片描述
2、class文件生成

資源打包過程中生成的R.java文件中包含了資源的id,java代碼中通過這些id可以尋找到相關的資源。R.java類和項目中其他java源碼,以及aidl接口通過java compiler生成.class文件。

在這裏插入圖片描述
3、dex文件生成

上面項目源碼中生成的class文件和第三方庫通過dex生成.dex文件,Android運行在Dalvik Virtual Machine上,和Java不同,Java運行在jvm上,Dalvik Virtual Machine上運行的不是.class文件,而是.dex文件。
可以使用android-sdk中的dexdump 工具來反編譯dex文件。dexer工具可以把class文件轉換成.dex文件。

在這裏插入圖片描述

dex的優點
dexer打包工具會消除class文件中的冗餘信息,所有的class文件會被打包進同一個dex文件中,使用dex會很大的減少apk的大小,下面表格是使用dex工具後文件的大小對比:
在這裏插入圖片描述
由上表可知使用dex文件可以極大的減少應用的大小。

2、apk結構

在這裏插入圖片描述

由上圖可以看出apk主要由META-INF,assets,res,lib,resources.arsc,classes.dex,AndroidManifest.xml,等8個部分組成,下面分別對這個8個組成進行分析。
1、META-INF
apk實際上是一個包含了各種結構信息的jar文件,META-INF文件夾包含了manifest信息和jar的包信息META-INF主要包括下圖的三個部分組成:
在這裏插入圖片描述

1、MANIFEST.MF:包含導入jar運行時的信息,包括運行時啓動哪個main class。package的版本號,build number。package的創建者信息,安全和允許證書信息等。

2、CERT.SF: 包含所有文件列表信息以及文件的SHA-1摘要。

3、CERT.RSA: 包含CERT.SF文件的簽名內容以及用於對該內容簽名的公鑰證書。

一個簡單的META-INF文件

Manifest-Version: 1.0
Created-By: 1.7.0_60 (Oracle Corporation)

Name: res/drawable-xxhdpi-v4/common_plus_signin_btn_text_dark_pressed.9.png
SHA1-Digest: Db3E0/I85K9Aik2yJ4X1dDP3Wq0=

Name: res/drawable-xhdpi-v4/opt_more_item_close_press.9.png
SHA1-Digest: Xxm9cr4gDbEEnnYvxRWfzcIXBEM=

Name: res/anim/accessibility_guide_translate_out.xml
SHA1-Digest: dp8PyrXMy2IBxgTz19x7DATpqz8=

2、RES

res會在R.java生成索引ID,在打包的時候判斷資源有沒有用到,沒用到的時候不會被打包進apk中(res/raw文件夾除外), res用getResource()訪問,res/raw裏的文件在打包的時候不會被系統二進制編譯,都被原封不動打包進APK,通常用來存放遊戲資源、腳本、字體文件等,res/xml會被編譯成二進制文件。res/anim存放動畫資源。
在這裏插入圖片描述
注意:res中的資源不會被編譯進 resources.arsc中。

assets和res的區別

在這裏插入圖片描述

3、resources.arsc

Android編譯過程中Android的資源打包工具(Android Asset Packaging Tool)aapt,會生成一個R.java文件,這個文件保存layout,styles,等資源的唯一id。並且生成一個resources.arsc文件,這個文件中保存了資源的屬性信息比如:
1、xml文件的節點(LinearLayout, RelativeLayout)
2、佈局的屬性( android:layout_width)
3、資源的id
resources.arsc中的信息會在運行的時候被解析。

3、減少apk大小

由上面知道了apk的組成,可知要減少apk的大小就是要減少上面apk組成中的各個模塊的大小,減小包大小的方法如下圖所示:
在這裏插入圖片描述

減少資源數目移除無用資源

1、使用lint工具進行檢測

res/layout/preferences.xml: Warning: The resource R.layout.preferences appears
    to be unused [UnusedResources]

注意lint不會檢測asset文件夾中的文件

2、使用shrinkResources

如果如果在 app的build.gradle 文件中配置shrinkResources屬性,gradle會自動移除無用資源

android {
    // Other settings

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

進行了上面的配置後在build的過程中,ProGuard會先移除無用的代碼但是不會移除無用的資源,Gradle會移除無用的資源。

減少動畫幀

幀動畫由於每一幀都是一幅圖片所以非常容易增加apk的大小,減少幀數能夠非常有效的減少apk大小。下面是一個幀率爲30的動畫包含的圖片,在這裏插入圖片描述
包含了接近30張圖片,如果把幀數換成15,圖片數目會減少一半。

使用xml定義純色圖片

有些圖片並不需要靜態的圖片資源,對於一些純色的圖片儘量使用用shape,color的xml文件來代替圖片,使用xml定義的shape能夠有效的減少apk大小。

複用圖片資源

在開發中有些圖片只是顏色不一樣,有些圖片只是大小不一樣,有些圖片只是角度不一樣。Android提供了相應的方法來複用這些圖片。

<?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" />

壓縮圖片

Android Asset Packaging Tool
Android Asset Packaging Tool簡稱aapt,AAPT 能夠查看,創建,更新,zip文件,並且能夠將資源編譯成二進制文件,是Android sdk中自帶的打包class和resource工具。

The Android Asset Packaging Tool (aapt) takes your application
resource files, such as the AndroidManifest.xml file and the XML files
for your Activities, and compiles them。

能夠在:..\android-sdk\build-tools\<buildToolsVersion>包中找到。

aapt命令的使用

  • 創建apks (Android application bundles)
aapt package, aapt add 
  • aapt dump 查看apk的信息:
    1、查看版本號:
aapt dump badging name.apk

2、查看權限:

aapt dump permissions name.apk

使用aapt工具對圖片進行壓縮,aapt工具在build過程中能對res/drawable/文件夾下的文件進行無損壓縮。

aapt的缺點
1、aapt不會壓縮 asset/文件夾下的png圖片
2、
3、aapt不會過濾已經壓縮過的圖片,所以會對已經壓縮過的圖片造成影響,爲了避免這種影響可以在gradle中使用

aaptOptions {
    cruncherEnabled = false
}

減少使用枚舉

一個枚舉類會造成class.dex增大1.0到1.4kb大小。
If possible, consider using the @IntDef annotation and ProGuard to strip enumerations out and convert them to integers. This type conversion preserves all of the type safety benefits of enums

參考文獻

1、https://stackoverflow.com/questions/6517151/how-does-the-mapping-between-android-resources-and-resources-id-work

2、https://stackoverflow.com/questions/27548810/android-compiled-resources-resources-arsc

3、https://developer.android.com/guide/topics/resources/providing-resources.html#AlternativeResources

4、https://developer.android.com/reference/android/widget/ImageView#attr_android:tint

5、https://developer.android.com/guide/topics/graphics/vector-drawable-resources

6、https://stackoverflow.com/questions/28234671/what-is-aapt-android-asset-packaging-tool-and-how-does-it-work/28234924

7、https://elinux.org/Android_aapt

8、https://developer.android.com/guide/topics/resources/providing-resources#Accessing
9、https://stackoverflow.com/questions/39305775/what-are-the-purposes-of-files-in-meta-inf-folder-of-an-apk-file/39305776
10、https://stackoverflow.com/questions/5583608/difference-between-res-and-assets-directories
11、https://stackoverflow.com/questions/18951048/how-does-the-android-build-process-work

12、https://stuff.mit.edu/afs/sipb/project/android/docs/tools/building/index.html

13、https://medium.com/@kevalpatel2106/how-you-can-decrease-application-size-by-60-in-only-5-minutes-47eff3e7874e

14、https://stackoverflow.com/questions/7750448/what-are-dex-files-in-android

15、https://source.android.com/devices/tech/dalvik/dex-format.html

發佈了186 篇原創文章 · 獲贊 675 · 訪問量 64萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章