Android性能優化:APK瘦身方式大彙總

大家都知道開發中應用程序的性能是非常重要的,將直接影響用戶的體驗,但是性能優化是個老生常談的問題,我們需要慢慢來,本篇文章將從如何減少APK的大小開始,來提升Android App的性能,這裏只是列舉了一些方式方法,讀者可根據自身應用需要對自己的APK進行相應處理。

用戶經常會避免下載看起來太大的應用程序,尤其是在設備連接到2G和3G網絡或付費網絡的應用市場內部。這篇文章講述如何減少您的應用程序APK的大小,以便使更多的用戶下載您的應用程序。

理解APK文件結構

在討論如何降低您的應用程序的大小之前,理解一個應用程序的APK的文件結構它是非常有幫助的。一個APK文件包含一個ZIP歸檔,主要包含您的應用程序的所有文件。這些文件包括Java類文件,資源文件,和包含編譯的文件資源。

一個APK包含如下目錄:

  • META_INF/:包含CERT.SFCERT.RSK 簽名文件,以及MANIFEST.MF清單文件。

  • assets/:包含應用程序的資產,應用程序可以使用一個AssetManager對象檢索。

  • res/:包含不能被編譯進resources.arsc文件的資源。

  • lib/:包含編譯後的代碼,是特定於處理器的軟件層。這個目錄包含爲每個平臺類型分配的子目錄,像armeabi,armeabi-v7a,arm64-v8a,x86,x86_64,和mips。 但是優化 APK還包含以下文件。其中,只有AndroidManifest.xml是強制性的。

  • resources.arsc:包含編譯的資源。這個文件包含來自文件夾res/values/下所有配置的XML內容。包裝工具提取這個XML內容,將它編譯成二進制形式並且歸檔這些內容。這個內容包括語言字符串和樣式以及路徑下不存在於resources.arsc文件的內容,比如佈局文件和圖片。

  • classes.dex:包含DEX文件中編譯的類可以被 Dalvik/ART 虛擬機理解的格式。

  • AndroidManifest.xml:包含Android的核心清單文件。這個文件列出了應用的名稱,版本,訪問權限,以及引用的庫文件的應用程序。文件使用Android的二進制XML格式。

減少資源的數量和大小

APK的大小影響應用程序的加載速度,對內存的使用,和它對電量的消耗。一個使您的APK較小的簡單方式是減少它包含資源的數量和大小。特別是,您可以移除應用程序不再使用的資源,和您可以使用可拉伸的Drawable圖像文件。本節討論這些方法以及其他幾個方法都是通過減少您的應用程序使用的資源來減少您的APK總體規模。

移除不使用的資源

Android Studio 內部包含一個靜態代碼分析器lint工具,使用它可以檢索資源文件夾res/,找出您的代碼不引用的資源。當lint工具在您的工程中發現一個潛在的未被使用的資源,它會打印一條消息就像下面的例子。

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

⚠️:lint工具不能掃描assets/目錄,通過反射引用assets,或您連接庫文件到您的應用。同時,它不會刪除資源;只提醒你他們的存在

您的代碼依賴的庫文件或許包含不被使用的資源。如果在您的build.gradle構建文件中啓用shrinkResources,它表示Gradle會自動刪除這些資源。

android {
    // Other settings

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

爲了使用shrinkResources,你必須啓用代碼壓縮。在構建過程中,首先ProGuard刪除未被使用的代碼但是閒置未被使用的資源。然後Gradle移除未被使用的資源。

關於ProGuard和其它Android Studio提供的途徑,幫助您減少APK大小的更多的信息,可以參照Shrink Your Code and Resources

在Android Gradle插件0.7和更高版本上,您可以聲明您的應用程序支持的配置。Gradle通過使用resConfigresConfigs類別以及默認配置defaultConfig選項,去構建系統。然後構建系統可以防止不受支持的配置的資源,出現在APK文件中,從而減少APK文件的大小。關於此功能的更多信息,可以查看 Remove unused alternative resources

最小化來自於外部庫資源的使用

當我們開發一個Android應用程序時,您通常使用外部庫來提高應用程序的可用性和多功能性。例如,您可以引用Android Support Library來改善應用程序在舊設備上的用戶體驗,或者您可以在您的應用程序內部使用Google Play Services來檢索文本,對其進行自動翻譯。

如果一個庫被設計用於一個服務器或桌面。它可能包括許多您的應用程序不需要的對象和方法。爲了做到只包括您需要的部分,如果庫的證書允許您可以編輯該庫的文件。您還可以使用一個替代的方法,移動指定的功能模塊到您的應用程序。

⚠️:ProGuard可以清除一些不必要的代碼導入庫,但是不能移除一個庫龐大的內部依賴關係。

僅僅支持特定密度

Android支持一組非常大的設備,包括各種各樣的屏幕密度。在Android 4.4(API級別19)和更高版本,該框架支持各種密度:ldpimdpitvdpihdpixhdpixxhdpixxxhdpi。即使Android支持所有的這些密度,您也不需要爲每個密度導出相應的資源。

如果您知道只有一小部分用戶的設備擁有特定的密度,這些密度是否需要包括到您的應用程序中那是值得考慮的。對應於一個特定的屏幕密度,如果您不包括相應的資源,Android會根據其它屏幕密度,找尋與之相近的現有資源。

如果您的應用程序只需要按比例縮小的圖像,在drawable-nodpi/文件下放置唯一圖像即可,這樣您可以節省更多的空間。我們建議每一個應用程序包括至少一個xxhdpi圖像變體。

關於屏幕密度的更多信息,可以參見Screen Sizes and Densities

使用drawable對象

一些圖像不要求一個靜態的圖片資源;框架可以在運行時動態畫出圖像。Drawable對象(<shape>在XML內)在您的APK內部可以佔用少量的空間。另外,XMLDrawable對象產生的單色圖像符合材料設計(material design)的指導方針。

減少資源

對於一個圖像的變化,您可以包括一個單獨的資源,如着色、陰影或旋轉版本相同的圖像。不管怎樣,我們建議您重用相同的一組資源,在運行時根據需要自定義它們。

Android 提供了一些工具來改變資源的顏色,在Android5.0(API21)和更高的版本上可以使用android:tint和tintMode屬性。對於較低的平臺版本,可以使用ColorFilter類。

對於一種資源經過旋轉可以得到另一種資源,您可以只導入一個。下面的代碼片段提供了一個示例:將一個“thumb up”繞軸旋轉180度轉變成“thumb down”:

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

圖像通過代碼渲染

您還可以通過程序渲染您的圖片,進而減少您的APK大小。程序渲染騰出空間,因爲您不需要存儲圖片到你的APK文件中。

Crunch PNG 文件

在構建過程中,aapt工具可以使用無損壓縮方式優化放置在res/drawable/目錄下的圖像資源,進而降低圖片空間佔用。例如,the aapt tool can convert a true-color PNG that does not require more than 256 colors to an 8-bit PNG with a color palette(這句不好翻譯).這樣轉換之後,相同質量的圖像會佔用更小的內存。

請注意,aapt擁有以下限制:

  • aapt不能壓縮asset/目錄下的PNG文件。
  • aapt工具優化圖像文件需要使用256或更少的顏色。
  • aapt工具可能多次優化已經壓縮過的PNG文件。爲了避免這個您可以在Gradle文件中使用cruncherEnabled標誌禁用對PNG文件的處理。
aaptOptions {
    cruncherEnabled = false
}

壓縮 PNG 和 JPEG 文件

您可以在不丟失圖像質量的情況下使用工具減少 PNG 文件的大小,像 pngcrush, pngquant, or zopflipng。所有這些工具可以減少PNG文件的大小,同時保留感知的圖像質量。

pngcrush工具是特別有效的:這個工具遍歷PNG過濾器和zlib(Deflate)參數,使用過濾器和參數的組合壓縮圖像。然後選擇壓縮效果最好的配置輸出(It then chooses the configuration that yields the smallest compressed output)。

爲了壓縮 JPEG 文件,你可以使用工具比如: packJPG and guetzli.

使用 WebP 格式文件

針對Android 3.2(API級別13)和更高版本,您還可以使用WebP圖像格式文件,而不是使用 PNG 和 JPEG 文件。WebP格式提供了有損壓縮(如JPEG)以及透明度(如PNG),相較於JPEG或PNG它可以提供更好的壓縮。

使用Android Studio,您可以轉換存在的 BMP,JPG,PNG 或 靜態的GIF圖像爲 WebP格式。更多的信息,請參考 Create WebP Images Using Android Studio

⚠️:谷歌市場接受APK的啓動圖標只能是PNG格式。

使用矢量圖

您可以使用矢量圖形創建分辨率無關圖標和其他可伸縮的媒體。使用這些圖形可以大大減少你的APK大小。在Android中,矢量圖表示爲VectorDrawable對象。VectorDrawable對象,一個100字節的文件可以用於呈現屏幕大小的圖像。

然而,系統需要大量的時間來呈現每個VectorDrawable對象,且圖像越大呈現到屏幕上所需要的時間越長。因此,考慮只有當顯示小圖像時使用這些矢量圖形。

更多的關於VectorDrawable對象如何工作的信息,可以參考Working with Drawables

使用矢量圖形動畫圖像

不能使用 AnimationDrawable對象去創建幀動畫,因爲這樣做對於每一幀動畫都需要包括一個單獨的bitmap文件,這大大增加APK的大小。

您應該使用AnimatedVectorDrawableCompat去創建矢量動畫

減少 native 和 Java 代碼

這裏有幾種方法可以用來減少在您的應用程序中 Java 和 native 代碼庫的大小。

移除不必要生成的代碼

確定瞭解由工具自動生成的任何代碼的足跡(Make sure to understand the footprint of any code which is automatically generated)。例如,許多協議緩衝工具生成過多的方法和類,它可以使您的應用程序大小提升兩倍或三倍。

避免使用枚舉

一個枚舉可以使您的應用程序的classes.dex文件增加約 1.0 到 1.4 KB大小。對於複雜系統或共享庫這些添加可以迅速增大此文件。如果可能的話,可以考慮使用@IntDef註解和ProGuard去剝離枚舉,取出將它們轉換爲整數。這種類型的轉換保存所有的枚舉類型是安全可靠的。

減少本地二進制文件的大小

如果您的應用程序使用本地代碼和Android NDK,你也可以減少你的應用程序的發佈版本的大小,以優化你的代碼。兩個有用的技術去除調試符號而不是提取本地庫。

移除調試符號

使用調試符號的意義,在於您的應用程序在開發過程中仍然需要調試。使用arm-eabi-strip工具(Android NDK 提供),從本地庫刪除不必要的調試符號。 之後,您可以編譯發佈構建。

避免提取本地庫

在構建應用程序的發佈版本時,如果您在你的應用程序的清單文件中,元素標籤下設置屬性如下android:extractNativeLibs="false",則APK包將不會壓縮.so文件。禁用這個標誌可以在應用的安裝過程中,阻止PackageManager從您的APK拷貝.so文件到文件系統,這樣做的好處是讓您更新您的應用程序更小。

維護多個精簡的 APKS

APK可能包含一些用戶下載但從未使用的內容,如區域或語言信息。爲用戶創建一個最小的下載,你可以將您的應用程序分割成幾個apk,分化的因素如屏幕大小或GPU硬件的支持。

當用戶下載您的應用程序,他們的設備基於設備的功能和設置接收到正確的APK。這種方式,設備沒有接收到資產設備沒有的功能。例如,如果用戶擁有一個hdpi設備,他們不需要相對於更高密度的設備包括的xxxhdpi資源。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章