1. 程式人生 > >Android打包-基礎知識-Android程式設計師必回

Android打包-基礎知識-Android程式設計師必回

從開始著手公司app安卓原生版本的開發,到如今2.3釋出,已經過了快半年的時間,在這半年的時間裡,已經逐漸掌握了Android 打包的一些基礎知識。今天在這裡小小梳理一下,順便總結下安卓打包中需要注意的問題和一些有效的經驗。

打包過程介紹

首先,需要注意的是不管是打什麼包,或者用什麼工具打包,其背後都是執行的Android提供的構建系統。所以我們先從每個過程介紹一下Android Build系統是如何一步一步將 java檔案、資原始檔、第三方庫等打包成APK的。

Paste_Image.png

資原始檔的預編譯

打包過程的第一步,便是資原始檔的預編譯,資原始檔包括所有位於res/目錄下的所有檔案以及所有的AndroidManifest檔案,在這一步中Android使用aapt

工具將資原始檔進行編譯,生成R檔案。R檔案中每個ID的生成都有一個特殊的規則,每個id都是一個四位元組的數字 0x PPTTNNNN, 第一個位元組PP代表了資原始檔代表的包名,在Android應用程式中PP始終是7f。第二個位元組TT代表了資原始檔的型別,aapt從0開始每發現一種新的資源型別就加1,最後面兩個位元組NNNN代表了資原始檔在該型別中的順序索引,跟TT類似,從0開始每發現一個新的資原始檔名就加1。比如我們看一下我們工程中生成的R檔案

id資源

menu資源

我們可以使用appt命令輸出打包好的apk中所有的資原始檔列表

appt dump resources <path-to-apk>

AIDL檔案編譯

AIDL 全稱Android Interface definition language。在Android如果涉及到多程序比如遠端service的時候就需要去定義aidl檔案,用來統一描述進行間通訊的介面。

interface IMyAidlInterface {    
    /**     * Demonstrates some basic types that you can use as parameters     * and return values in AIDL.     */    
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,            double aDouble, String aString);
}

Android打包時會將aidl檔案轉化為一個同名的java介面,如下圖所以,可以在/build/generated/source/aidl下看到。

 

AIDL打包

Java檔案的編譯

這一步是標準的java檔案編譯的過程,編譯的輸入既包括我們手動編寫的程式碼也包括前兩步中生成java檔案。編譯的輸出為.class檔案。

生成.dex檔案

第四步將上一步生成的class檔案,以及引用的第三方庫中的class檔案一起轉化為Dalvik位元組碼。

雖然Android使用Java語言程式設計。但是Android並不使用標準的Java虛擬機器進行java code。Android有自己的虛擬機器 Dalvik以及5.0以上的ART。 可以大致瞭解一下Dalvik虛擬機器和傳統虛擬機器的區別:

  • Dalvik虛擬機器佔用記憶體更少
  • JVM是基於Stack的(Stack based),DVM是基於Register的(Register based). 跟進一步說,JVM將區域性變數存在stack中,而DVM將變數儲存在register中。因此標準java虛擬機器需要更多的指令集,而DVM的指令集更少,另一方面DVM需要用暫存器編碼指令的source 和 destination ,因此Dalvik的一條指令更長。
  • 在JVM執行時,會根據需要去load每個class檔案。而Dalvik中所有的class都在一個dex檔案中。

基於第三條區別,我們在前第三步中生成的所有class檔案以及第三庫中引用的class檔案都需要一起整合為一個dex檔案。

JVM_vs_DVM.jpg

不過這裡有一個潛在的危險,由於dex設計上的原因,單個dex內最多能引用的方法數上限為65536,這個數字對於當今很多APP來說都已經不夠用了,不行的是,我們專案中就碰到了。不過Google也早早就放出瞭解決方案。這裡就不詳細討論了,有興趣瞭解可以戳這裡

資原始檔打包

第一步資原始檔已經使用aapt進行了預編譯,是為了 讓所有引用了資源的java檔案正常編譯,這裡在打包之前,Android build system需要將所有的資原始檔進行打包。這裡依然是使用第一步中用到的aapt工具。打包後會生成一個resources-debug.ap_檔案,這個檔案中包含了圖片,layout,menu,anim, AndroidManifest,其中圖片都經過了優化,xml檔案被編譯成二進位制格式。string被編譯成單獨的resources.arsc檔案。

打包APK

第五步就是打包APK了,這一步的工作就是將dex檔案,資原始檔(編譯的和未編譯的)打包在一塊,生成apk。

簽名

第五步生成的apk檔案,必須經過簽名才能安裝在裝置上。簽名前,我們必須生成自己的keystore

$ keytool -genkey -v -keystore my-release-key.keystore-alias alias_name -keyalg RSA -keysize 2048 -validity 10000

使用keytool,生成一個keystore,這個keystore包含一個有效期10000天的key。

要對apk進行簽名,需要用到java提供的簽名工具

$ jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1-keystore my-release-key.keystore my_application.apk alias_name

如果需要驗證某個apk是否簽名過,可以使用

jarsigner -verify -verbose -certs my_application.apk

對齊

打包apk的最後一步是一個對齊工作。這一步的工具簡而言之就是使apk內所有未壓縮的所有檔案相對於apk的其實位置都是4位元組對齊的。這樣,這些檔案既可以直接使用mmap對映訪問。這樣做的目的是為了減少app在執行時所佔用的記憶體。

zipalign -c -v 4 application.apk



作者:呆萌狗和求疵喵
連結:https://www.jianshu.com/p/45da3b9b0ac8
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。