日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

Android APK 打包过程 MD

發(fā)布時(shí)間:2023/11/30 Android 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android APK 打包过程 MD 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Markdown版本筆記我的GitHub首頁(yè)我的博客我的微信我的郵箱
MyAndroidBlogsbaiqiantaobaiqiantaobqt20094baiqiantao@sina.com

Android APK 打包流程 MD


目錄

目錄
APK 的打包流程
整體流程
資源的編譯和打包
資源ID
資源索引
概況
具體打包過(guò)程
aapt階段
aidl階段
Java Compiler階段
dex階段
apkbuilder階段
Jarsigner階段
zipalign階段

APK 的打包流程

參考

Android的包文件APK分為兩個(gè)部分:代碼和資源,所以打包方面也分為資源打包和代碼打包兩個(gè)方面,這篇文章就來(lái)分析資源和代碼的編譯打包原理。

Android打包流程詳圖:

整體流程

APK整體的的打包流程如下圖所示:

具體說(shuō)來(lái):

  • 通過(guò)AAPT工具進(jìn)行資源文件(包括AndroidManifest.xml、布局文件、各種xml資源等)的打包,生成R.java文件。
  • 通過(guò)AIDL工具處理AIDL文件,生成相應(yīng)的Java文件。
  • 通過(guò)Javac工具編譯項(xiàng)目源碼,生成Class文件。
  • 通過(guò)DX工具將所有的Class文件轉(zhuǎn)換成DEX文件,該過(guò)程主要完成Java字節(jié)碼轉(zhuǎn)換成Dalvik字節(jié)碼,壓縮常量池以及清除冗余信息等工作。
  • 通過(guò)ApkBuilder工具將資源文件、DEX文件打包生成APK文件。
  • 利用KeyStore對(duì)生成的APK文件進(jìn)行簽名。
  • 如果是正式版的APK,還會(huì)利用ZipAlign工具進(jìn)行對(duì)齊處理,對(duì)齊的過(guò)程就是將APK文件中所有的資源文件舉例文件的起始距離都偏移4字節(jié)的整數(shù)倍,這樣通過(guò)內(nèi)存映射訪問(wèn)APK文件的速度會(huì)更快。

上述流程都是Android Studio在編譯時(shí)調(diào)用各種編譯命令自動(dòng)完成的,具體說(shuō)來(lái),如下所示:

1、創(chuàng)建Android工程。

android create project \
-n packageTest2 \
-a MainActivity \
-k com.package.test2 \
-t android-23 \
-p ./PackageTest2

2、編譯R文件

aapt package \
-f \
-J ./gen \
-M ./AndroidManifest.xml \
-S ./res/ \
-I /Users/RadAsm/Library/AndroidSDK/sdk/platforms/android-23/android.jar

3、編譯源代碼文件

javac -source 1.6 \
-target 1.6 \
-cp /Users/RadAsm/Library/AndroidSDK/sdk/platforms/android-23/android.jar \
./src/com/packtest/test1/MainActivity.java ./src/com/packtest/test1/R.java \
-d ./gen/classes

4、編譯DEX文件

dx --dex \
--verbose \
--output ./gen/dex/packtest1.dex
./gen/classes/

5、生成APK文件

aapt package
-f \
-J ./gen \
-M ./AndroidManifest.xml \
-S ./res/ \
-I /Users/RadAsm/Library/AndroidSDK/sdk/platforms/android-23/android.jar \
-F ./output/res.apk

6、APK文件對(duì)齊

zipalign -v -p 4 packagetest_unsigned.apk packagetest_aligned_unsigned.apk

7、APK簽名

apksigner sign --ks my-release-key.jks my-app.apk

以上便是APK打包的整個(gè)流程,我們?cè)賮?lái)總結(jié)一下:

  • 除了assets和res/raw資源被原裝不動(dòng)地打包進(jìn)APK之外,其它的資源都會(huì)被編譯或者處理;
  • 除了assets資源之外,其它的資源都會(huì)被賦予一個(gè)資源ID;
  • 打包工具負(fù)責(zé)編譯和打包資源,編譯完成之后,會(huì)生成一個(gè)resources.arsc文件和一個(gè)R.java,前者保存的是一個(gè)資源索引表,后者定義了各個(gè)資源ID常量。
  • 應(yīng)用程序配置文件AndroidManifest.xml同樣會(huì)被編譯成二進(jìn)制的XML文件,然后再打包到APK里面去。
  • 應(yīng)用程序在運(yùn)行時(shí)通過(guò)AssetManager來(lái)訪問(wèn)資源,或通過(guò)資源ID來(lái)訪問(wèn),或通過(guò)文件名來(lái)訪問(wèn)。

理解了整體的流程,我們?cè)賮?lái)看看具體的細(xì)節(jié)。

資源的編譯和打包

在分析資源的編譯和打包之前,我們先來(lái)了解一下Android程序包里有哪些資源。

我們知道Android應(yīng)用程序的設(shè)計(jì)也是代碼與資源相分離的,Android的資源文件可以分為兩大類:

assets:assets資源放在主工程assets目錄下,它里面保存一些原始的文件,可以以任何方式來(lái)進(jìn)行組織,這些文件最終會(huì)原封不動(dòng)的被打包進(jìn)APK文件中。

獲取asset資源也十分簡(jiǎn)單,如下所示:

InputStream is = getAssets.open("fileName");

res:res資源放在主工程的res目錄下,這類資源一般都會(huì)在編譯階段生成一個(gè)資源ID供我們使用。

res資源包含了我們開(kāi)發(fā)中使用的各種資源,具體說(shuō)來(lái):

  • animator
  • anim
  • color
  • drawable
  • layout
  • menu
  • raw
  • values
  • xml

這些資源的含義大家應(yīng)該都很熟悉,這里就不再贅述。

上述9種類型的資源文件,除了raw類型資源,以及Bitmap文件的drawable類型資源之外,其它的資源文件均為文本格式的XML文件,它們?cè)诖虬倪^(guò)程中,會(huì)被編譯成二進(jìn)制格式的XML文件。這些二進(jìn)制格式的XML文件分別有一個(gè)字符串資源池,用來(lái)保存文件中引用到的每一個(gè)字符串,包括XML元素標(biāo)簽、屬性名稱、屬性值,以及其它的一切文本值所使用到的字符串。這樣原來(lái)在文本格式的XML文件中的每一個(gè)放置字符串的地方在二進(jìn)制格式的XML文件中都被替換成一個(gè)索引到字符串資源池的整數(shù)值,這寫整數(shù)值統(tǒng)一保存在
R.java類中,R.java會(huì)和其他源文件一起編譯到APK中去。

前面我們提到xml編寫的Android資源文件都會(huì)編譯成二進(jìn)制格式的xml文件,資源的打包都是由AAPT工具來(lái)完成的,資源打包主要有以下流程:

  • 解析AndroidManifest.xml,獲得應(yīng)用程序的包名稱,創(chuàng)建資源表。
  • 添加被引用資源包,被添加的資源會(huì)以一種資源ID的方式定義在R.java中。
  • 資源打包工具創(chuàng)建一個(gè)AaptAssets對(duì)象,收集當(dāng)前需要編譯的資源文件,收集到的資源保存在AaptAssets對(duì)象對(duì)象中。
  • 將上一步AaptAssets對(duì)象保存的資源,添加到資源表ResourceTable中去,用于最終生成資源描述文件resources.arsc。
  • 編譯values類資源,這類資源包括數(shù)組、顏色、尺寸、字符串等值。
  • 給bag、style、array這類資源分配資源ID。
  • 編譯xml資源文件,編譯的流程分為四步:① 解析xml文件 ② 賦予屬性名稱資源ID ③ 解析屬性值 ④ 將xml文件從文本格式轉(zhuǎn)換為二進(jìn)制格式。
  • 生成資源索引表resources.arsc。

資源ID

每個(gè)Android項(xiàng)目里都有有一個(gè)R.java文件,如下所示:

public final class R {//...public static final class anim {public static final int abc_fade_in=0x7f010000;}public static final class attr {public static final int actionBarDivider=0x7f020000;}public static final class string {public static final int actionBarDivider=0x7f020000;}//... }

每個(gè)資源項(xiàng)后的整數(shù)就是資源ID,資源ID是一個(gè)4字節(jié)的無(wú)符整數(shù),如下所示:

  • 最高字節(jié)是Package ID表示命名空間,標(biāo)明資源的來(lái)源,Android系統(tǒng)自己定義了兩個(gè)Package ID,系統(tǒng)資源命名空間:0x01 和 應(yīng)用資源命名空間:0x7f。
  • 次字節(jié)是Type ID,表示資源的類型,例如:anim、color、string等。
  • 最低兩個(gè)字節(jié)是Entry ID,表示資源在其所屬資源類型中所出現(xiàn)的次序。

資源索引

上面提到,最終生成的是資源索引表resources.arsc,Android正是利用這個(gè)索引表根據(jù)資源ID進(jìn)行資源的查找,為不同語(yǔ)言、不同地區(qū)、不同設(shè)備提供相對(duì)應(yīng)的最佳資源。查找是通過(guò)Resources和AssetManger來(lái)完成的,這個(gè)我們下面會(huì)講。

resources.arsc 是一個(gè)編譯后的二進(jìn)制文件,在Android Stduio里打開(kāi)以后是這樣的,如下所示:

可以看到resources.arsc里存放了各類資源的索引參數(shù)和配置信息。

resources.arsc的文件格式如下所示:

注:整個(gè)文件都是有一系列chuck(塊)構(gòu)成的,chuck是整個(gè)文件的劃分單位,每個(gè)模塊都是一個(gè)chuck,chuck最前面是一個(gè)ResChunk_header的結(jié)構(gòu)體,用來(lái)描述整個(gè)chunk的信息,更多關(guān)于索引表格式的細(xì)節(jié),可以查閱源碼:

? ResourceTypes.h

resources.arsc 索引表從上至下文件格式依次為:

  • 文件頭:數(shù)據(jù)結(jié)構(gòu)用ResTable_header來(lái)描述,用來(lái)描述整個(gè)文件的信息,包括文件頭大小,文件大小,資源包Package的數(shù)量等信息。
  • 全局字符串池:存放所有的字符串,所以資源復(fù)用這些字符串,字符串里存放的是資源文件的路徑名和資源值等信息。全局字符串池分為資源類型(type)字符串池和
  • 資源包:會(huì)有多個(gè)(例如:系統(tǒng)資源包、應(yīng)用資源包)。

資源包也被劃分為以下幾個(gè)部分:

  • 包頭:描述資源包相關(guān)信息。
  • 資源類型字符串池:存放資源的類型。
  • 資源名稱字符串池:存放資源的名稱。
  • 配置列表:存放語(yǔ)音、位置等手機(jī)配置信息,用來(lái)作為查找資源的標(biāo)準(zhǔn)。

從這里可以看到resources.arsc索引表存在很多常量池,常量池的使用目的也很明顯,就是提供資源的復(fù)用率,減少resources.arsc索引表的體積,提高索引效率。

概況

參考

Android APK是如何來(lái)的呢?

懷著這個(gè)問(wèn)題去查資料,發(fā)現(xiàn)了下邊這張圖。

解壓一個(gè)普通的apk文件后,解壓出來(lái)的文件包括:

  • classes.dex:.dex文件
  • resources.arsc:resources resources文件
  • AndroidManifest.xml:AndroidManifest.xml文件
  • res:uncompiled resources
  • META-INF:簽名文件夾
    • MANIFEST.MF文件:版本號(hào)以及每一個(gè)文件的哈希值(BASE64),包括資源文件。這個(gè)是對(duì)每個(gè)文件的整體進(jìn)行SHA1(hash)。
    • CERT.SF:這個(gè)是對(duì)每個(gè)文件的頭3行進(jìn)行SHA1 hash。
    • CERT.RSA:這個(gè)文件保存了簽名和公鑰證書。

具體打包過(guò)程

aapt階段

使用aapt來(lái)打包res資源文件,生成R.java、resources.arsc和res文件(二進(jìn)制 & 非二進(jìn)制如res/raw和pic保持原樣)

  • res目錄,有9種子目錄
  • R.java文件。里面擁有很多個(gè)靜態(tài)內(nèi)部類,比如layout,string等。每當(dāng)有這種資源添加時(shí),就在R.java文件中添加一條靜態(tài)內(nèi)部類里的靜態(tài)常量類成員,且所有成員都是int類型。
  • resources.arsc文件。這個(gè)文件記錄了所有的應(yīng)用程序資源目錄的信息,包括每一個(gè)資源名稱、類型、值、ID以及所配置的維度信息。我們可以將這個(gè)文件想象成是一個(gè)資源索引表,這個(gè)資源索引表在給定資源ID和設(shè)備配置信息的情況下,能夠在應(yīng)用程序的資源目錄中快速地找到最匹配的資源。

aidl階段

AIDL,Android接口定義語(yǔ)言,Android提供的IPC的一種獨(dú)特實(shí)現(xiàn)。
這個(gè)階段處理.aidl文件,生成對(duì)應(yīng)的Java接口文件。

Java Compiler階段

通過(guò)Java Compiler編譯R.java、Java接口文件、Java源文件,生成.class文件。

dex階段

通過(guò)dex命令,將.class文件和第三方庫(kù)中的.class文件處理生成classes.dex。

apkbuilder階段

將classes.dex、resources.arsc、res文件夾(res/raw資源被原裝不動(dòng)地打包進(jìn)APK之外,其它的資源都會(huì)被編譯或者處理)、Other Resources(assets文件夾)、AndroidManifest.xml打包成apk文件。

Jarsigner階段

對(duì)apk進(jìn)行簽名,可以進(jìn)行Debug和Release 簽名。

zipalign階段

release mode 下使用 aipalign 進(jìn)行align,即對(duì)簽名后的apk進(jìn)行對(duì)齊處理。

Zipalign是一個(gè)android平臺(tái)上整理APK文件的工具,它對(duì)apk中未壓縮的數(shù)據(jù)進(jìn)行4字節(jié)對(duì)齊,對(duì)齊后就可以使用mmap函數(shù)讀取文件,可以像讀取內(nèi)存一樣對(duì)普通文件進(jìn)行操作。如果沒(méi)有4字節(jié)對(duì)齊,就必須顯式的讀取,這樣比較緩慢并且會(huì)耗費(fèi)額外的內(nèi)存。

在 Android SDK 中包含一個(gè)名為 zipalign 的工具,它能夠?qū)Υ虬蟮?app 進(jìn)行優(yōu)化。 其位于 SDK 的 \build-tools\23.0.2\zipalign.exe 目錄下

2019-2-18

轉(zhuǎn)載于:https://www.cnblogs.com/baiqiantao/p/10398653.html

總結(jié)

以上是生活随笔為你收集整理的Android APK 打包过程 MD的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。