您好,登錄后才能下訂單哦!
這篇文章主要講解了“如何理解Android APK的結構構成”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“如何理解Android APK的結構構成”吧!
一、 APK 組成解析
1.1 Apk 分析工具
1.2 Dex 知識點拓展
二、 構建源碼導讀
2.1 源碼引入
2.2 BuildConfig Task 詳解
2.3 獲取所有 task 對應的類名
三、構建流程梳理
四、手動構建 APK
作者:hockeyli,騰訊 PCG 客戶端開發工程師
在開始解析 Android 構建流程之前,我們先來看下構建的最終產物 APK 的整體組成:
APK 主要由五個部分組成,分別是:
Dex:.class 文件處理后的產物,Android 系統的可執行文件
Resource:資源文件,主要包括 layout、drawable、animator,通過 R.XXX.id 引用
Assets:資源文件,通過 AssetManager 進行加載
Library:so 庫存放目錄
META-INF:APK 簽名有關的信息
工欲善其事,必先利其器,既然想分析 APK 必然少不了好用的工具。
① Android Studio 自帶的 APK 分析器
通過 APK 分析器,我們可以完成這些操作:
查看 APK 中文件(如 DEX 和 Android 資源文件)的絕對大小和相對大小
了解 DEX 文件的組成
快速查看 APK 中文件(如 AndroidManifest.xml)的最終版本
對兩個 APK 進行并排比較
② ClassyShark 可以做為 AS 自帶 APK 分析器的補充,幫我們分析 dex 中的詳細數據,以及查看 APK 中的總方法數以及各個模塊的方法數分布。
當我們在 Android 查看一個 APK 的時候,可以看到右上角有 Defined Methods 和 Referenced Methods,但大多數人可能不知道這兩者的區別,這里簡單說明下:
Defined Methods:在這個 Dex 中定義的方法;Referenced Methods:Defined Methods 以及 Defined Methods 引用到的方法。
Android 有 64K 引用限制,當 type_ids、method_ids 或者 field_ids 超過 65536(64 * 1024)的時候,需要進行 dex 分包,為了 Dex 的數量盡可能少,我們需要盡量實現「Dex 信息有效率」的提升。
Dex 信息有效率 = Defined Methods 數量 / Referenced Methods 數量
當我們用 Android Studio 進行安裝包構建的時候,會發現其實是運行了一連串的 Task,也就是說其實是這些 task 的配合,最終構建出我們的 APK 的。
如果我們想更了解 Android 的構建流程,對于相關的源碼肯定是要有所了解的。那我們如何看到這些 Task 相關的源碼呢,我們知道 Android 是用 Gradle 進行構建的,也就意味著這些 task 其實都是放在 Gradle 中,我們想看 Gradle 中源碼的話,可以在 build.gradle 將 Gradle 進行編譯。
compileOnly "com.android.tools.build:gradle:3.0.1"
編譯完之后,可以在 ApplicationTaskManager#createTasksForVariantScope 中找到創建這些 Task 相關的代碼,也就意味著順藤摸瓜找到這些 Task 的真正實現邏輯。
這里以 BuildConfig 文件的生成為例,來梳理下如何查看某個 task 的代碼邏輯。
生成 BuildConfig 文件,是通過 ApplicationTaskManager 中通過 createBuildConfigTask 來創建對應的 task。
順著代碼邏輯,我們找到最終真正實現這個邏輯的是:GenerateBuildConfig 這個 task,GenerateBuildConfig 是繼承自 BaseTask,這里有個小技巧是,Task 中真正的執行邏輯都是在帶著 @TaskAction 注解的方法上的,所以我們能很快找到對應的 generate() 方法。可以看到生成 BuildConfig 整體的邏輯還是比較簡單的,其實就是將 build.gradle 中自帶的屬性以及我們自定義的屬性進行讀取,然后通過 JavaWriter 生成對應的 BuildConfig 文件。
看到上面的例子,可能有些人會拋出一個疑問就是那我們怎么確定構建中執行的 task 具體對應哪個類呢,這里提供一個小技巧,其實我們可以在 taskGraph 構建完成之后,將所有 task name 以及對應的 class 進行打印。例如在 build.gradle 中加入這個代碼之后,我們在運行的時候,就會把 task 所對應的類名也都一起打印出來。
可以看到 Android 構建中會涉及到多個工具,我們可以通過 open $ANDROID_HOME/build-tools 來查看相關的構建工具。
最后我們通過命令行來手動打包一個可執行的 APK,能讓我們對 APK 構建的理解更加深入。首先需要準備下 代碼、資源文件、AndroidManifest 這些構建 APK 的必要文件。
① 通過 aapt2 compile 將 res 資源編譯成 .flat 的二進制文件:
aapt2 compile -o build/res.zip --dir res
② 通過 aapt2 link 將 .flat 和 AndroidManifest 進行連接,轉化成不包含 dex 的 apk 和 R.java:
aapt2 link build/res.zip -I $ANDROID_HOME/platforms/android-30/android.jar --java build --manifest AndroidManifest.xml -o build/app-debug.apk
③ 通過 javac 將 Java 文件編譯成 .class 文件:
javac -d build -cp $ANDROID_HOME/platforms/android-30/android.jar com/**/**/**/*.java
④ 通過 d8 將 .class 文件轉化成 dex 文件:
d8 --output build/ --lib $ANDROID_HOME/platforms/android-30/android.jar build/com/tencent/hockeyli/androidbuild/*.class
⑤ 合并 dex ?件和資源?件:
zip -j build/app-debug.apk build/classes.dex
⑥ 對 apk 通過 apksigner 進行簽名:
apksigner sign -ks ~/.android/debug.keystore build/appdebug.apk
感謝各位的閱讀,以上就是“如何理解Android APK的結構構成”的內容了,經過本文的學習后,相信大家對如何理解Android APK的結構構成這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。