減少APK的大小,Android官方這樣說

RoxYali 8年前發布 | 7K 次閱讀 安卓開發 Android開發 移動開發

前言

最近項目終于到了收尾上線階段,由于引用了不少第三方的框架和SDK,導致APK非常的大。強迫癥犯了,就想減小APK的大小。到處搜索一下各路大神的方法。還是覺得無論從原理上還是具體做法上都是官方的比較全面。所以就翻譯了一下,分享出來。主要是用Google Translate,然后自己稍微按照中文邏輯修了一下。如有不妥的地方,請多提意見。(PS:另外還碰到了傳奇的65535方法數這個大坑,后面再寫這個。文中有些超鏈接可能需要梯子)

用戶經常會避免下載看起來過大的應用程序,特別是在新興市場,設備連接到常見的2G和3G網絡或著使用按字節付費的網絡。本文介紹如何減少應用程序的APK大小,讓更多使用者下載你的應用程序。

一、了解APK結構

在討論如何縮小應用程序的大小之前,先了解應用程序APK的結構,是有幫助的。APK文件包含ZIP文件,其中包含構成應用程序的所有文件。這些文件包括Java類文件,資源文件和已編譯資源的文件。

APK包含以下目錄:

  • META-INF/: 包含 CERT.SF 和 CERT.RSA 簽名文件,以及 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: 包含以Dalvik / ART虛擬機理解的DEX文件格式而編譯的類。
  • AndroidManifest.xml: 包含核心Android清單文件。此文件列出應用程序的名稱,版本,訪問權限和引用的庫文件。該文件使用Android的二進制XML格式。

二、減少資源數量和大小

APK的大小會影響你的應用加載速度,使用的內存以及它消耗的電量。使APK更小的簡單方法之一是減少它包含的資源的數量和大小。特別是,你可以刪除你的應用程序不再使用的資源,你可以使用可擴展的 Drawable 對象代替圖像文件。本節討論這些方法以及其他幾種可以減少應用程序資源從而減少APK整體大小的方法。

刪除未使用的資源

lint 工具,是一個在Android Studio中的靜態代碼分析器,用來檢測你的代碼中沒有用到的 res / 文件夾中的資源。

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

注意: lint 工具不掃描 assets/ 文件夾,它是通過反射來發現引用的資源或已鏈接到你的應用程序的庫文件。此外,它不會刪除資源;它只會提醒你們他們的存在。

你添加到代碼的庫可能包含未使用的資源。如果在應用程序的 build.gradle 文件中啟用 shrinkResources ,Gradle可以自動刪除資源。

android {
    // Other settings

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

}</code></pre>

要使用 shrinkResources ,必須啟用代碼縮減。在構建過程中,首先要用 ProGuard 刪除未使用的代碼,但留下未使用的資源。然后Gradle刪除未使用的資源。

有關ProGuard和Android Studio幫助你減少APK大小的其他方法的詳細信息。

在Android Gradle Plugin 0.7及更高版本中,你可以聲明你的應用程序支持的配置。 Gradle使用 resConfig 、 resConfigs flavor 和 defaultConfig 選項并將此信息傳遞給構建系統。然后,構建系統會阻止來自其他不受支持的配置的資源出現在APK中,從而減少APK的大小。

最小化庫中的資源使用

開發Android應用程序時,通常使用外部庫來提高應用程序的可用性和多功能性。

例如,你可以引用 Android Support Library 以改善舊設備上的用戶體驗,或者你可以使用 Google Play Services 檢索應用內文字的自動翻譯。

如果庫是為服務器或桌面設計的,它可能包括你的應用程序不需要的許多對象和方法。要僅包含應用程序需要的庫的部分,你可以編輯庫的文件(如果許可證允許你修改庫)。你也可以使用其他適合移動設備的庫給你的應用添加特定功能。

注意: ProGuard 可以清理引用庫導入的一些不必要的代碼,但它不能刪除庫的大型內部依賴項 。

僅支持特定密度

Android支持非常大的設備集,包括各種屏幕密度。在Android 4.4(API級別19)及更高版本中,框架支持各種密度: ldpi , mdpi , tvdpi , hdpi , xhdpi , xxhdpi 和 xxxhdpi 。雖然Android支持所有這些密度,但你不需要細化資源到適合每個密度。

如果你知道只有一小部分用戶使用具有特定密度的設備,請考慮是否需要將這些密度捆綁到應用中。如果你不包括特定屏幕密度的資源,Android會自動縮放最初為其他屏幕密度設計的現有資源。

如果你的應用只需要縮放的圖片,你可以通過在drawable-nodpi /中使用圖片的單個變體來節省更多空間。我們建議每個應用程序至少包含一個 xxhdpi 圖片版本。

減少動畫幀

逐幀動畫會大幅增加APK的大小。圖1顯示了在目錄中分成多個PNG文件的逐幀動畫的示例。每個圖像是動畫中的一幀。

對于添加到動畫中的每個幀,都需要增加APK中存儲的圖片數量。在圖1中,圖像在應用程序中以30 FPS動畫。如果圖像僅以15FPS動畫化,則動畫將僅需要所需幀的數目的一半。

圖1.作為資源存儲的逐幀動畫。

使用Drawable對象

一些圖像不需要靜態圖像資源; framework可以在運行時動態地繪制圖像。

(XML中的 <shape> )可能會占用你APK中的少量空間。此外,XML對象還能產生符合 Material Design 準則的單色圖像。

重用資源

你可以為圖像的變體使用單一的資源,例如同一圖像的有色,陰影或旋轉版本。但是,我們建議你重復使用相同的資源集,在運行時根據需要進行自定義。

Android提供了幾個實用程序來更改資產的顏色,使用Android 5.0(API級別21)或更高版本上的 android:tint 和 tintMode 屬性。對于較低版本的平臺,請使用 ColorFilter 類。

你還可以省略只是等效于另一個資源的資源。以下代碼段提供了一個例子,通過簡單地將原始圖像旋轉180度,將“展開”箭頭轉換為“折疊”箭頭圖標:

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

從代碼中呈現

你還可以通過程序性渲染圖片來減少APK大小。這個過程也釋放了空間,因為你不再在APK中存儲圖像文件。

壓縮PNG文件

aapt 工具可以在構建過程期間優化放置在 res / drawable / 中的圖像資源,以及無損壓縮。例如, aapt 工具可以將不需要多于256種顏色的真彩色PNG轉換為帶有調色板的8位PNG。這樣做會產生質量相同但占用內存較小的映像。

請記住, aapt 有以下限制:

  • aapt 工具不會壓縮資源/文件夾中包含的PNG文件
  • 圖像文件需要使用256個或更少的顏色的 aapt 工具來優化它們。
  • aapt 工具可能會使已壓縮的PNG文件膨脹。為了防止這種情況,你可以在Gradle中使用 cruncherEnabled 標志為PNG文件禁用此過程:
    aaptOptions {
      cruncherEnabled = false
    }

壓縮PNG和JPEG文件

你可以使用像 pngcrush , pngquant ,或 zopflipng 等工具來減少PNG文件大小,而不會丟失圖像質量。所有這些工具都可以減少PNG文件大小,同時保持圖像質量。

pngcrush 工具特別有效:此工具在PNG過濾器和zlib(Deflate)參數上迭代,使用過濾器和參數的每個組合來壓縮圖像。然后選擇產生最小壓縮輸出的配置。

對于JPEG文件,你可以使用 packJPG 等工具將JPEG文件壓縮為更緊湊的形式。

使用WebP文件格式

除了使用PNG或JPEG文件,你還可以為你的圖像使用 WebP 文件格式。 WebP格式提供有損壓縮(如JPEG)和透明度(如PNG),還可以提供比JPEG或PNG更好的壓縮效果。

但是,使用WebP文件格式有一些顯著的缺點。 首先,在低于Android 3.2(API級別13)的平臺的版本中不支持WebP。 第二,系統解碼WebP比PNG文件需要更長的時間。

注意:只有當所包含的圖標使用PNG格式時,Google Play才接受APK。如果你打算通過Google Play發布應用,則無法對應用圖標使用其他文件格式(如JPEG或WebP)。

使用矢量圖形

你可以使用矢量圖形創建獨立于分辨率的圖標和其他可伸縮圖片。 使用這些圖形可以大大減少APK的大小。 矢量圖形在Android中表示為 VectorDrawable 對象。 使用 VectorDrawable 對象,100字節的文件可以生成屏幕大小的清晰圖像。 然而,系統渲染每個 VectorDrawable 對象需要大量的時間,較大的圖像需要更長的時間才能出現在屏幕上。 因此,只有在顯示小圖像時才考慮使用這些矢量圖形。

三、減少原生和Java代碼

有幾種方法可以用來減少應用程序中Java和原生代碼庫的大小。

刪除不必要的生成的代碼

確保了解自動生成的任何代碼的足跡。例如,許多協議緩沖工具生成過多的方法和類,可以使應用程序的大小增加一倍或三倍。

刪除枚舉

單個枚舉可以使應用程序的 classes.dex 文件添加大約1.0到1.4 KB的大小。 這些添加可以快速積累為復雜的系統或共享庫。 如果可能,請考慮使用 @IntDef 注釋和 ProGuard 來除去枚舉并將它們轉換為整數。 此類型轉換保留枚舉的所有類型的安全性好處。

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

如果你的應用使用原生代碼和Android NDK,你還可以通過優化代碼來減小應用的大小。兩個有用的技術是刪除調試符號和提取原生庫。

  • 刪除調試符號

    如果你的應用程序正在開發中并仍需要調試,則使用調試符號很有意義。 使用Android NDK中提供的 arm-eabi-strip 工具從本機庫中刪除不必要的調試符號。 之后,你可以編譯你的發行版。
  • 避免提取原生庫

    將 .so 文件存儲在APK中未壓縮的文件,并在應用清單的 <application> 元素中將 android:extractNativeLibs 標記設置為false。 這將防止 PackageManager 在安裝過程中將 .so 文件從APK復制到文件系統,并且將具有使你的應用程序的delta更新更小的額外好處。

四、維護多個精益版APK

你的APK可以包含用戶下載但從不使用的內容,例如區域或語言信息。 要為用戶創建最低限度的下載,你可以將應用細分為多個APK,并根據屏幕尺寸或GPU紋理支持等因素進行區分。

當用戶下載你的應用時,其設備會根據設備的功能和設置接收正確的APK。這樣,設備不會接收設備沒有的功能的資源。例如,如果用戶具有 hdpi 設備,則他們可能不需要你為具有更高密度顯示的設備添加的 xxxhdpi 資源。

 

來自:http://www.jianshu.com/p/6df0dc494019

 

 本文由用戶 RoxYali 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!