實際上,一個APK文件就是一個.zip格式的壓縮包,我們可以用解壓縮工具打開任何一個APK文件,由於代碼混淆和加密,通過普通解壓縮工具打開里面的文件或目錄會看到各種亂碼。一個典型的apk文件包含以下內容:
•AndroidManifest.xml
Android應用的配置清單文件,它向Android系統介紹了這個應用的很多配置信息,系統可以根據這個文件在相當程度上了解這個應用的一些信息。該文件是每個應用都必須定義和包含的,它描述了應用的名字、版本、權限、引用的庫文件等等信息,如要把apk上傳到Google Market上,也要對這個xml做一些配置。在apk中的AndroidManifest.xml是經過壓縮的,可以通過AXMLPrinter2工具(針對該文件)或apktool工具進行反編譯(反編譯整個apk)。
•META-INF目錄
META-INF目錄下存放的是簽名信息,用來保證apk包的完整性和系統的安全。沒有簽名的應用是不被系統認可的,也無法安裝到手機中。Android SDK在對APK進行打包的時候,會把APK中全部文件的完整信息保存到這里,這樣應用在安裝的時候會進行完整性校驗,確保APK的文件不會被篡改,大大提升了應用和系統的安全性與完整性。META-INF目錄下有CERT.RSA、CERT.SF和MANIFEST.MF這幾個文件,其中的CERT.RSA文件記錄了開發者的私鑰對APK簽名后的信息,MANIFEST.MF文件則保存了整個APK中所有文件的SHA-1進行base64編碼后的值,CERT.SF則與MANIFEST.MF差不多,包括了后者所有的信息,然后又加入了MANIFEST.MF文件的SHA-1並base64編碼的值。
•res目錄
存放各種資源文件的目錄。這個目錄中的所有文件,最終會被映射到Android工程中的R文件中,生成對應的int型的ID,在程序中訪問這些資源文件的時候,直接使用資源的ID就能進行調用了。
•lib目錄
•assets目錄
跟res目錄有點相似,但實際上二者還是有區別的。res目錄中的文件會映射到R文件中,每個資源文件都有自己的ID,而assets中的文件則直接通過訪問文件的地址來使用AssetManager類進行訪問,而且assets目錄你可以添加任意深度的子目錄,這一點會比較方便管理和歸類文件。相比較之下,res目錄目前不能支持更深級的子目錄。
Android應用的配置清單文件,它向Android系統介紹了這個應用的很多配置信息,系統可以根據這個文件在相當程度上了解這個應用的一些信息。該文件是每個應用都必須定義和包含的,它描述了應用的名字、版本、權限、引用的庫文件等等信息,如要把apk上傳到Google Market上,也要對這個xml做一些配置。在apk中的AndroidManifest.xml是經過壓縮的,可以通過AXMLPrinter2工具(針對該文件)或apktool工具進行反編譯(反編譯整個apk)。
•META-INF目錄
META-INF目錄下存放的是簽名信息,用來保證apk包的完整性和系統的安全。沒有簽名的應用是不被系統認可的,也無法安裝到手機中。Android SDK在對APK進行打包的時候,會把APK中全部文件的完整信息保存到這里,這樣應用在安裝的時候會進行完整性校驗,確保APK的文件不會被篡改,大大提升了應用和系統的安全性與完整性。META-INF目錄下有CERT.RSA、CERT.SF和MANIFEST.MF這幾個文件,其中的CERT.RSA文件記錄了開發者的私鑰對APK簽名后的信息,MANIFEST.MF文件則保存了整個APK中所有文件的SHA-1進行base64編碼后的值,CERT.SF則與MANIFEST.MF差不多,包括了后者所有的信息,然后又加入了MANIFEST.MF文件的SHA-1並base64編碼的值。
•res目錄
存放各種資源文件的目錄。這個目錄中的所有文件,最終會被映射到Android工程中的R文件中,生成對應的int型的ID,在程序中訪問這些資源文件的時候,直接使用資源的ID就能進行調用了。
res目錄下還包含着多個子文件夾:anmi中存放着動畫文件;drawable則存放着一些圖片資源;layout中存放的是布局文件;menu則是自定義菜單的項;raw目錄中的文件則是可以直接復制到設備中的文件,不會被編譯;values中存放着一些特殊的值——colors.xml記錄的是你自定義的顏色,dimens.xml記錄着你自定義的尺寸,strings.xml則是你自定義的字符串常量值,styles.xml定義了一些樣式。
•lib目錄
這個目錄中存放着應用依賴的native庫文件,這些以.so結尾的文件是用C或者C++語言編寫的,一個簡單的Android應用可能並不需要這些庫,但一個功能全面而又追求性能的應用是不可能無視這個目錄的,譬如圖片處理、網絡處理、音視頻處理等一些對性能要求很高的功能,單純依靠Java會十分吃力,性能更加強大而且更加接近底層的C/C++就是更合適的選擇了。
根據手機CPU的架構,lib庫大體上可以分為4種:ARM、ARM-V7、MIPS和X86,分別對應着4種CPU架構,在lib目錄里則分別是armeabi、armeabi-v7a、mips和x86一共4個目錄。每個目錄中的.so庫名字都是一樣的,實際上功能也是相同的,它們只是為了適配不同架構的CPU而存在。實際上,市面上的手機幾乎全都是ARM架構的,所以大多數情況下我們只需要有armeabi和armeabi-v7a兩種類型的庫就足夠了。
•assets目錄
跟res目錄有點相似,但實際上二者還是有區別的。res目錄中的文件會映射到R文件中,每個資源文件都有自己的ID,而assets中的文件則直接通過訪問文件的地址來使用AssetManager類進行訪問,而且assets目錄你可以添加任意深度的子目錄,這一點會比較方便管理和歸類文件。相比較之下,res目錄目前不能支持更深級的子目錄。
classes.dex是java源碼編譯后生成的java字節碼文件(首先是java文件通過jdk編譯成字節碼文件然后經過dex編譯成classes.dex)。但由於Android使用的dalvik虛擬機與標准的java虛擬機是不兼容 的,dex文件與class文件相比,不論是文件結構還是opcode都不一樣。目前常見的java反編譯工具都不能處理dex文件。Android模擬 器中提供了一個dex文件的反編譯工具,dexdump。用法為首先啟動Android模擬器,把要查看的dex文件用adb push上傳的模擬器中,然后通過adb shell登錄,找到要查看的dex文件,執行dexdump xxx.dex。
對比普通java程序和安卓程序差異:
普通java程序 java虛擬機 java字節碼(class) 基於棧
安卓程序 Davlik虛擬機 Dalvik字節碼(dex) 基於寄存器
•resources.arsc
編譯后的二進制資源文件的索引,記錄了資源文件(即res目錄中的文件)和資源文件ID的映射關系,這樣程序運行的時候就可以根據資源的ID獲取到相應的資源了。
普通java程序 java虛擬機 java字節碼(class) 基於棧
安卓程序 Davlik虛擬機 Dalvik字節碼(dex) 基於寄存器
•resources.arsc
編譯后的二進制資源文件的索引,記錄了資源文件(即res目錄中的文件)和資源文件ID的映射關系,這樣程序運行的時候就可以根據資源的ID獲取到相應的資源了。
