SmallerAPK,第1部分:APK的剖析
如果我問一堆開發人員他們的應用程式的大小是什麼,我很確定大多數人會檢視Android Studio生成的APK檔案並告訴我他們的計算機佔用了多少磁碟空間。這是最直接的答案,它在技術上是正確的,但也許我應該問更好的問題。考慮這些例如:
- 安裝在使用者裝置上時,您的應用佔用了多少空間?
- 使用者下載和安裝應用程式需要支付多少網路資料?
- 現有使用者的應用更新下載大小有多大?
- 執行應用程式的記憶體佔用量(就使用的RAM而言)是多少?
如果您是一名擁有高階手機的開發人員,您可能想知道是否值得花時間優化APK大小...請記住,並非所有裝置都具有相同的儲存,記憶體或網路連線。
世界上有些地方使用者必須為他們下載的每兆位元組資料付費,而且每個角落都沒有Wi-Fi熱點。
有些裝置沒有內部儲存容量(磁碟空間)來讓使用者安裝他們需要的所有應用程式,這意味著他們必須在安裝或更新任何軟體之前三思而後行。誰知道,這些可能是你的下一個千萬或幾百萬使用者,所以讓我們試著讓那個APK更小!它將使每個人受益。
當然,考慮到我們都必須處理的各種要求和約束,很難選擇一刀切的解決方案。有時,犧牲初始下載大小將加速後續更新。在其他情況下,與直覺相反,在APK中保持檔案未壓縮可以減少裝置上的最終磁碟空間量。我將嘗試突出這些權衡並在適用的地方提供解釋,但最終由您(開發人員)選擇對您的應用和使用者有意義的混合技術。
執行時記憶體佔用空間大多超出了本系列文章的範圍。所呈現的優化可能對記憶體使用和效能產生一些小的副作用,包括正面和負面。我會嘗試在適用的時候提及任何明顯的缺點,但是由讀者來衡量你的應用程式的效能特徵並進行最後的呼叫。記住,#permatmatters!
什麼是APK
在我開始討論如何縮小應用程式之前,讓我們首先看一下檔案格式本身。APK實際上只是一個ZIP存檔,包含構成應用程式的檔案。通常在APK中,您會找到以下條目:
classes.dex
包含已編譯的應用程式程式碼,轉換為Dex位元組碼。如果您使用multidex來克服65536方法限制,您可能會在APK中看到多個DEX檔案。從介紹ART執行時的Android 5.0開始,這些在安裝時由提前編譯器編譯成OAT檔案並放在裝置的資料分割槽上。您可以在第2部分:縮小程式碼中學習如何減小dex程式碼的大小
RES /
此資料夾包含大多數XML資源(例如佈局)和drawables(例如PNG,JPEG)在具有各種限定符的資料夾中,例如-mdpi和-hdpi用於密度,-sw600dp或-large用於螢幕大小和-en,-de,-pl對於語言。請注意,res /中的任何XML檔案在編譯時都已轉換為更緊湊的二進位制表示,因此您無法使用APK內部的文字編輯器開啟它們。
第3部分:刪除未使用的資源顯示瞭如何通過在專案中使用陳舊資源來確保不浪費空間。在第4部分:多APK,ABI和密度分割以及第5部分:通過產品風格的多APK中,我們討論如何根據硬體特徵在多個APK上劃分資產,這些APK針對特定裝置組。第6部分:影象優化,Zopfli和WebP以及第7部分:影象優化,Shape和VectorDrawables處理各種優化技術,使影象更小。
resources.arsc
一些資源和識別符號被編譯並展平到此檔案中。它通常儲存在APK中而不進行壓縮,以便在執行時更快地訪問。手動壓縮此檔案似乎很容易獲勝,但實際上至少有兩個原因並不是一個好主意。一,Play Store壓縮任何資料以進行傳輸和兩個,在APK內壓縮檔案會浪費系統資源(RAM)和效能(尤其是app啟動時間)。
第3部分將展示兩種方法,通過僅包含對您的應用有意義的語言的字串,使該檔案更加精簡。
AndroidManifest.xml中
與其他XML資源類似,您的應用程式清單在編譯期間轉換為二進位制格式。Play商店使用AndroidManifest中包含的某些資訊來決定是否可以在裝置上安裝APK,檢查允許的密度或螢幕大小以及可用的硬體和功能(例如觸控式螢幕)。如果要在編譯後檢查這些Manifest條目,可以使用Android SDK中的aapt工具:
$ aapt dump badging your_app.apk
庫/
任何本機庫(* .so檔案)都將放在以libs /資料夾為目標的ABI(CPU架構,例如x86,x86_64,armeabi-v7a)命名的子資料夾中。通常,它們會在安裝時從APK複製到您的/ data分割槽。但是,由於APK本身在使用者裝置上不會被更改,因此這實際上會使任何本機庫所需的空間翻倍。本文的第8部分(本機庫,從APK開啟)為Android 6.0+上的此問題提供瞭解決方案,還可以在舊裝置上節省網路頻寬。
資產/
此資料夾用於任何不會用作Android型別資源的檔案資產。最常見的是字型檔案或遊戲資料,如關卡和紋理,以及您希望直接作為檔案流開啟的任何其他應用程式資料。
META-INF /
此資料夾存在於已簽名的APK中,幷包含APK及其簽名中所有檔案的列表。目前在Android中籤名的方式是,它逐個驗證來自存檔的未壓縮檔案內容的簽名。
這有一些有趣的後果。由於ZIP檔案中的每個條目都是單獨儲存的,這意味著您可以更改單個檔案的壓縮級別而無需重新簽名。但是,如果您在簽名後從歸檔中刪除任何檔案,則簽名驗證將失敗。
關於如何建立已簽名的APK的另一個注意事項是zipalign工具用作構建的最後一個階段。如果您手動更改存檔的內容,通常您需要重新簽名,然後在將APK上傳到Play商店之前進行zipalign。
使用Zopfli重新壓縮APK(不要這樣做)
更新:此前本文包含一個部分,使用更強大的壓縮演算法Zopfli重新壓縮APK中的檔案。此功能現在已從Android Studio 2.2中的構建工具中刪除,不再推薦使用,因為它可能會影響將Play Store增量更新更小的未來計劃。
如果您仍然不相信停止使用Zopfli作為您的APK,讀者已經提醒我,某些Android 5.0.1裝置可能在閱讀Zopfli壓縮的APK時遇到問題,甚至可能導致您的應用崩潰。
無論如何,本指南的下一章應該是您的主要關注點,並且比使用Zopfli為APK提供多10倍的節省。
+qq群457848807:。獲取以上高清技術思維圖,以及相關技術的免費視訊學習資料
相關文章
- Spring 事務管理高階應用難點剖析: 第 1 部分Spring
- 《Divinuet》的互動音樂系統 – 第 1 部分
- WebSphere Process Server 流量管理,第 1 部分WebServer
- Spring 的優秀工具類盤點第 1 部分Spring
- Spring 事務管理高階應用難點剖析: 第 2 部分Spring
- Spring 事務管理高階應用難點剖析: 第 3 部分Spring
- 架構設計師與SOA, 第 1 部分架構
- mORMot模糊概念--FormatSQL-第1部分ORMSQL
- 遊戲音訊存檔 | 第 1 部分:基本情況遊戲音訊
- 整合 WebSphere Process Server 與 SCA 功能包,第 1 部分WebServer
- 通用執行緒:Awk 例項,第 1 部分(轉)執行緒
- Vim 實用技術,第 1 部分: 實用技巧
- 13 款驚豔的 Node.js 框架——第1部分Node.js框架
- Django入門指南-第1部分(環境搭建)Django
- 如何構建一個多人(.io) Web 遊戲,第 1 部分Web遊戲
- [譯] 除錯 RxJS 第1部分: 工具篇除錯JS
- 在Docker Swarm上部署Apache Storm:第1部分DockerSwarmApacheORM
- Windows 到 Linux 之旅:第 1 部分. Linux 思想(轉)WindowsLinux
- 關於 Java Collections API 您不知道的 5 件事,第 1 部分JavaAPI
- 【譯】什麼是SOLID原則(第1部分)Solid
- [譯] Xcode 和 LLDB 高階除錯教程:第 1 部分XCodeLLDB高階除錯
- 輕鬆學習 JavaScript——第 1 部分:瞭解 let 語句JavaScript
- Webpack 系列第 3 部分Web
- [Flutter翻譯]Flutter Anatomy - 佈局內部的第1部分Flutter
- Java XML和JSON:Java SE的文件處理,第1部分JavaXMLJSON
- [譯]使用 Rust 開發一個簡單的 Web 應用,第 1 部分RustWeb
- 預示敏捷方法走偏的15個標誌——第1部分敏捷
- 使用感測器監控的 Smarter Planet 解決方案,第 1 部分
- Vue文件中幾個易忽視部分的剖析Vue
- [譯] 使用深度學習自動生成 HTML 程式碼 - 第 1 部分深度學習HTML
- 使用 LLVM 框架建立一個工作編譯器,第 1 部分LVM框架編譯
- 精通 R plot—第1部分:顏色,圖例和線
- 使用 React.js 的漸進式 Web 應用程式:第 1 部分 - 介紹ReactJSWeb
- PHPV5.3中的新特性,第1部分:物件介面的變化PHP物件
- 《WCF技術內幕》翻譯5:第1部分_第1章_藍月亮:WCF介紹和本章小結
- 《Divinuet》的互動音樂系統 – 第 2 部分
- 在Go中構建區塊鏈 第4部分:交易1Go區塊鏈
- 使用Go構建區塊鏈 第1部分:基本原型Go區塊鏈原型