APK的基本結(jié)構(gòu)

1.APK文件的含義及構(gòu)成
APK (Android application package)指 Android 應(yīng)用程序包,是 Android 系統(tǒng)中的一種文件格式,用來對安卓應(yīng)用程序的文件進(jìn)行打包。APK 文件包含了應(yīng)用程序的所有文件,包括靜態(tài)資源文件(assets)、庫文件(lib)、簽名文件(META-INF)、編譯資源文件(res)、配置清單文件(AndroidManifest.xml)、核心代碼文件(classes.dex)和資源映射文件(resources.arsc)等信息,APK文件的基本結(jié)構(gòu)示例見圖1。通常,可以從應(yīng)用市場或者網(wǎng)站下載 APK 文件,然后使用 Android 系統(tǒng)提供的安裝器安裝應(yīng)用程序。本文通過某APK文件解壓后的文件夾來介紹這些文件資源的作用。

2.?靜態(tài)資源文件
靜態(tài)資源文件主要指存放在assets 文件夾中的文件。assets 文件夾是一種未經(jīng)編譯的資源目錄,它會(huì)被打包進(jìn) APK 文件中,在安裝應(yīng)用程序之后可以被訪問。assets 文件夾中的文件不會(huì)被解壓縮,這意味著它們的訪問速度會(huì)比較快,但是會(huì)占用更多的安裝包空間。通常情況下,開發(fā)者會(huì)將應(yīng)用程序中的靜態(tài)文件、配置文件、原始數(shù)據(jù)或者其他不常改變的文件放在 assets 文件夾中。這樣可以使得應(yīng)用程序的下載包大小變小,并且可以更快速地訪問這些文件。
如圖2所示,在靜態(tài)資源assets文件夾中,可能存放一些圖片包括(jpg、png、gif等),還有可能存放js文件。
?

圖2 assets文件夾示例
3.庫文件
?

庫文件主要指lib文件夾中的文件,在這個(gè)文件夾中,存放了運(yùn)行APP所需要的so文件,也就是動(dòng)態(tài)鏈接庫的二進(jìn)制文件。為了適配不同安卓系統(tǒng)處理器的版本,lib文件夾中的so庫也是按不同處理器版本的文件夾分類放置。在圖3的示例中,分成了三種文件夾包括armeabi、armeabi-v7a和x86文件夾,分別用來存儲(chǔ)適配arm5架構(gòu)、arm7架構(gòu)、Intel32架構(gòu)的CPU處理器版本的安卓系統(tǒng)。例如,如果智能手機(jī)使用的是arm7架構(gòu)CPU處理器版本的安卓系統(tǒng),APP在運(yùn)行時(shí)就會(huì)調(diào)用armeabi-v7a文件夾下的動(dòng)態(tài)鏈接庫文件執(zhí)行程序。
在安卓系統(tǒng)中庫文件分文兩種,一種是共享庫文件(Shared Libraries),另一種是本地庫文件(Native Libraries)。共享庫文件是可供多個(gè)應(yīng)用程序使用的庫,它們被存放在系統(tǒng)目錄中。在 Android 系統(tǒng)中,共享庫文件以 .so 為后綴,常見的共享庫文件包括 libc.so 和 libm.so。
而lib文件夾存放的就是本地庫文件。本地庫是專門為應(yīng)用程序所使用的庫,它們被打包進(jìn) APK 文件中,在安裝應(yīng)用程序之后會(huì)被放到私有目錄中。在 Android 系統(tǒng)中,本地庫文件也以 .so 為后綴,armeabi-v7a的so文件示例見圖4。對于一個(gè) Android 應(yīng)用程序來說,本地庫文件往往是應(yīng)用程序所特有的,并且不會(huì)被其他應(yīng)用程序使用。例如,一個(gè)應(yīng)用程序可能使用本地庫文件來封裝特定的硬件訪問功能,或者使用本地庫文件來進(jìn)行加密解密操作。

4.簽名文件
?

簽名文件指的是存放在META-INF文件夾中的文件。META-INF 文件夾是 Android 系統(tǒng)中的一種特殊文件夾,它用來存放應(yīng)用程序的簽名信息。在 META-INF 文件夾中可以找到三種常見的文件:CERT.RSA、CERT.SF和MANIFEST.MF,META-INF文件夾示例見圖5。CERT.RSA、CERT.SF這兩個(gè)文件用來存放應(yīng)用程序的簽名信息。當(dāng)安裝一個(gè)應(yīng)用程序時(shí),Android 系統(tǒng)會(huì)檢查這兩個(gè)文件,以確保應(yīng)用程序的完整性和安全性。MANIFEST.MF文件用來存放應(yīng)用程序的所有文件的清單信息。
當(dāng)打包應(yīng)用程序時(shí),這些文件會(huì)自動(dòng)生成,并且會(huì)被打包進(jìn) APK 文件中。通常情況下,不需要手動(dòng)修改這些文件,但是有時(shí)候可能需要編輯這些文件來更新應(yīng)用程序的版本號或者修改權(quán)限要求。
META-INF文件夾,用于存放簽名證書,在APK安裝時(shí)作為校驗(yàn)的憑據(jù),用于保護(hù)APK不被惡意篡改,同時(shí)也是對APK著作權(quán)和所有權(quán)的聲明。例如,對安裝包的任意文件最作修改,導(dǎo)致安卓系統(tǒng)檢查計(jì)算后的簽名信息與APK文件中存儲(chǔ)的簽名信息不一致,最終無法安裝,會(huì)出現(xiàn)簽名沖突的問題。
5.編譯資源文件

編譯資源文件主要指存放在res文件夾中的文件。res文件夾,存放的也是資源文件,與assets文件夾不同的是,這里是編譯后的資源文件。直接打開可能顯示亂碼。在 res 文件夾中你會(huì)找到許多子文件夾,每個(gè)子文件夾都用來存放特定類型的資源文件,res文件夾示例見圖6。主要的文件夾包括drawable 文件夾、layout 文件夾和values 文件夾。
drawable 文件夾用來存放圖片資源文件,包括位圖文件(.png, .jpg, .gif 等)和矢量圖文件(.svg)。
layout 文件夾用來存放布局文件,布局文件用來描述應(yīng)用程序的界面結(jié)構(gòu)。
values 文件夾用來存放值資源文件,值資源文件用來存放應(yīng)用程序中使用的常量值和顏色信息。
在 Android 系統(tǒng)中,所有的資源文件都必須在 res 文件夾中存放,并且需要使用特定的文件名和文件夾名。這樣的好處是,Android 系統(tǒng)會(huì)自動(dòng)為每個(gè)資源文件分配一個(gè)唯一的資源 ID,使得安卓系統(tǒng)可以方便地引用這些資源。
6.配置清單文件
AndroidManifest.xml文件是配置清單文件,也是編譯過的文件,用來描述應(yīng)用程序的清單信息。包括包名、應(yīng)用名、權(quán)限、安卓四大組件、版本等重要信息都在這里面聲明。
當(dāng)打包應(yīng)用程序時(shí),AndroidManifest.xml 文件會(huì)自動(dòng)生成,并且會(huì)被打包進(jìn) APK 文件中。當(dāng)你安裝應(yīng)用程序時(shí),Android 系統(tǒng)會(huì)讀取這個(gè)文件,以確定應(yīng)用程序的基本信息和權(quán)限要求。
開發(fā)者可以在 AndroidManifest.xml 文件中聲明應(yīng)用程序使用的權(quán)限,例如訪問網(wǎng)絡(luò)、訪問文件、訪問相機(jī)等。在應(yīng)用程序安裝時(shí),用戶會(huì)看到這些權(quán)限的描述信息,然后決定是否允許應(yīng)用程序使用這些權(quán)限。
AndroidManifest.xml 文件還用來聲明應(yīng)用程序的主要組件,例如活動(dòng)(Activity)、服務(wù)(Service)、廣播接收器(BroadcastReceiver)等。這些組件是安卓應(yīng)用程序的四大組件的組成部分,它們負(fù)責(zé)實(shí)現(xiàn)應(yīng)用程序的功能。
7.核心代碼文件
核心代碼文件主要指classes.dex文件。classes.dex文件是 Android 系統(tǒng)中的重要代碼文件,它是 Dalvik 可執(zhí)行文件的縮寫。Dalvik 是 Android 系統(tǒng)中的一種虛擬機(jī),它負(fù)責(zé)在 Android 系統(tǒng)中運(yùn)行應(yīng)用程序的代碼。classes.dex文件運(yùn)行在Dalvik虛擬機(jī)上的核心代碼文件,它反編譯后的語言是smali代碼語言,smali代碼可轉(zhuǎn)換為java代碼。對于大的APK文件會(huì)出現(xiàn)多個(gè)dex文件,但在APP實(shí)際運(yùn)行的過程中會(huì)將多個(gè)dex文件合并成一個(gè)dex文件運(yùn)行。APK打包時(shí)存放多個(gè)dex的原因是每個(gè)dex文件的大小是有限制的。
.dex 文件中存放的是 Java 字節(jié)碼,這是 Java 編譯器編譯出來的機(jī)器碼。.dex 文件本身是一種二進(jìn)制文件,它使用一種特殊的格式來存放字節(jié)碼。
在打包 Android 應(yīng)用程序時(shí),.dex 文件會(huì)自動(dòng)生成,并且會(huì)被打包進(jìn) APK 文件中。當(dāng)你安裝應(yīng)用程序時(shí),.dex 文件會(huì)被解壓縮并放到私有目錄中,然后被 Dalvik 虛擬機(jī)加載并運(yùn)行。
.dex 文件的好處是,它可以使得應(yīng)用程序的下載包大小變小,因?yàn)?Java 字節(jié)碼文件可以被壓縮得比較小。但是,.dex 文件的缺點(diǎn)是,它的訪問速度略慢于共享庫文件。因此,在 Android 系統(tǒng)中,一般情況下會(huì)盡量使用共享庫文件來實(shí)現(xiàn)應(yīng)用程序的功能。
8.資源映射文件
resources.arsc 文件是 Android 系統(tǒng)中的一種特殊文件,它用來存放應(yīng)用程序的資源表。資源表是一種二進(jìn)制文件,它包含了應(yīng)用程序的資源 ID 和資源類型的映射關(guān)系。
在 Android 系統(tǒng)中,所有的資源文件都必須在 res 文件夾中存放,并且需要使用特定的文件名和文件夾名。當(dāng)你編譯應(yīng)用程序時(shí),編譯器會(huì)將 res 文件夾中的資源文件編譯成資源表,并且將資源表打包進(jìn) APK 文件中。
resources.arsc 文件的好處是,它可以使得應(yīng)用程序的資源文件變小,因?yàn)橘Y源表文件可以被壓縮得比較小。但是,resources.arsc 文件的缺點(diǎn)是,它的訪問速度略慢于普通的文本文件。因此,在 Android 系統(tǒng)中,一般情況下會(huì)盡量使用普通的文本文件來存放應(yīng)用程序的資源信息。
注意,resources.arsc 文件僅僅是一個(gè)輔助文件,它本身并沒有什么實(shí)際意義。應(yīng)用程序通常是通過資源 ID在這個(gè)資源映射表中尋找對應(yīng)的資源,來獲取相應(yīng)的參數(shù)。