APK打包過程

前言

HI兰迫,歡迎來到《每周一博》信殊。今天是一月第一周,也是2019年的第一周汁果,今天我給大家介紹下APK的結(jié)構(gòu)涡拘。

APK其實就是個壓縮文件,我們把后綴改成ZIP之后解壓就可以看到里面的內(nèi)容主要有如下部分:

1.AndroidManifest.xml
該文件是每個應(yīng)用都必須包含的据德,它描述了應(yīng)用的名字鳄乏,版本,權(quán)限棘利,引用的庫文件等等信息橱野。APK中的AndroidManifest.xml是二進制文件,直接打開是亂碼善玫,需要反編譯水援。

2.META-INF目錄
META-INF目錄下存放的是簽名信息,用來保證apk包的完整性和系統(tǒng)的安全。打包時會對所有要打包的文件做一個校驗計算蜗元,并把計算結(jié)果放在META-INF目錄下或渤。這就保證了apk包里的文件不能被隨意替換。比如拿到一個apk包后奕扣,如果想要替換里面的一幅圖片薪鹦,一段代碼, 或一段版權(quán)信息惯豆,想直接解壓縮池磁,替換再重新打包,基本是不可能的楷兽。如此一來就給病毒感染和惡意修改增加了難度地熄,有助于保護系統(tǒng)的安全。

3.classes.dex文件
classes.dex是java源碼編譯后生成的java字節(jié)碼文件拄养。安卓的虛擬機解析的是dex文件而不是class离斩。dex文件中各個類能夠共享數(shù)據(jù),在一定程度上降低了冗余瘪匿,也使得文件結(jié)構(gòu)更加經(jīng)湊跛梗,節(jié)省體積。

4.resources.arsc
resources.arsc是編譯后的二進制資源文件棋弥,它是一個映射表核偿,映射著資源和id,通過R文件中的id就可以找到對應(yīng)的資源顽染。

5.res目錄
res目錄存放資源文件漾岳,包括圖片,字符串等等粉寞,像layout尼荆,drawable中的xml文件也都是經(jīng)過編譯的,直接打開是亂碼唧垦,需要使用apktools才能查看捅儒。

6.lib目錄
lib目錄下存放的是一些so文件,如果代碼中沒有so就沒有該目錄振亮。

7.assets目錄
assets目錄下是一些配置文件巧还,也可以是資源,這里的xml文件不會經(jīng)過編譯坊秸,如果代碼中沒有assets也不會有該目錄麸祷。

編譯APK主要有如下幾步:

  1. 根據(jù)資源文件和AndroidManifest.xml生成R.java文件
  2. 編譯AIDL,生成對應(yīng)的java文件褒搔,沒有則跳過
  3. 編譯工程源碼(主項目和庫)阶牍,同時上邊生成的R文件和AIDL生成的Java文件也會被編譯生成相應(yīng)的class文件
  4. 將class文件打包生成dex文件
  5. 將資源文件打包喷面,生成初始的apk
  6. 將生成的dex文件加入到apk中生成未簽名的包
  7. 對apk進行簽名
  8. 將簽名后的apk進行對齊處理,目的是減少程序運行時對內(nèi)存的占用

這里有幾個圖可以幫助理解下荸恕。

粗略打包圖
詳細打包圖

本文介紹了APK的基本結(jié)構(gòu)乖酬,下周會介紹APK的具體打包過程死相,感謝大家的閱讀融求,我們下周再見。

前言

HI算撮,歡迎來到《每周一博》生宛。今天是一月第二周,我給大家介紹下APK的打包過程肮柜。這篇文章是在上一篇《APK結(jié)構(gòu)介紹》的基礎(chǔ)上進行實踐陷舅,先上一張詳細的打包流程圖。

詳細打包圖

接下來我們用工具手動打包一個Android項目审洞。

1. 配置環(huán)境變量

我們用到的工具在build-tools目錄下的不同版本中莱睁。

AAPT_HOME=/Users/peizhifei/Library/Android/sdk/build-tools/27.0.3/
export AAPT_HOME
export PATH=$PATH:$AAPT_HOME

創(chuàng)建一個測試項目,然后拷貝/Users/peizhifei/Library/Android/sdk/platforms/android-27/android.jar到項目根目錄

2. 創(chuàng)建輔助目錄

進入項目下面芒澜,生成gen存放R文件仰剿,build放過程文件,out放輸出文件痴晦。

cd app/src/main/
mkdir -p app/src/main/{gen,build,out}

3. 生成R文件

要使用aapt工具南吮,輸入Manifest和res和android.jar來生成R文件。

aapt p -f  -M ./app/src/main/AndroidManifest.xml  
-I  android.jar -S ./app/src/main/res/ -J ./app/src/main/gen/  -m

aapt命令參數(shù)含義:
-f : #如果編譯出來的文件已經(jīng)存在誊酌,強制覆蓋
-M : AndroidManifest.xml 的路徑
-I : android.jar的路徑
-S : 資源文件res 文件夾路徑
-J :生成 R.java 的輸出目錄
-m : 讓生成包的目錄放在 -J 參數(shù)指定的目錄
成功后可以再gen文件下會生成相應(yīng)的R.java文件部凑。

4. 編譯aidl文件

通過aidl工具就可以將aidl文件編譯成java文件。

aidl -Iapp/src app/src/main/aidl/com/example/peizhifei/myapplication/IMyAidlInterface.aidl

注意-Iapp/src之間是沒有空格的碧浊。

5. 編譯生成class文件

這一步就是用javac將項目中所有的java文件編譯成class文件涂邀。

javac -source 1.8 -target 1.8 -encoding UTF-8 
-bootclasspath android.jar -d app/src/main/build/ 
app/src/main/java/com/example/peizhifei/myapplication/*.java 
app/src/main/gen/com/example/peizhifei/myapplication/*.java 
app/src/main/aidl/com/example/peizhifei/myapplication/*.java

命令參數(shù)含義如下:
-encoding :編碼方式,這里設(shè)置UTF-8箱锐;
-bootclasspath :引導(dǎo)類文件的路徑比勉,這里需要使用到android.jar中的Android API;
-d :生成的class文件存放路徑瑞躺;
這里指定了所有的java文件敷搪,包括源碼的,aidl編譯的java文件幢哨,gen里面的R文件赡勘,結(jié)果存在在build下面。

6. 將class文件生成dex文件

dex文件是Android虛擬機可運行文件捞镰,可以使用dx工具生成闸与。

dx --dex --output=app/src/main/build/classes.dex app/src/main/build/

輸入是所有的class文件毙替,輸出在build下面,如果方法數(shù)超過Integer.Max多會出現(xiàn)多個dex文件践樱。

7. 生成資源映射表

資源索引表resources記錄了從資源id到文件路徑的轉(zhuǎn)換關(guān)系厂画,當(dāng)應(yīng)用通過R文件使用資源時,會先從resources中拿到文件路徑拷邢,然后通過AssetManager進行訪問袱院。

aapt package -f -M app/src/main/AndroidManifest.xml 
-I android.jar -S app/src/main/res/ -A app/src/main/assets 
-F app/src/main/out/resources

這里依然用到了aapt工具,如果有assets文件需要加進來瞭稼。成功后會在out目錄下看到resources文件忽洛。

8. 生成資源APK和編譯后的xml文件

這一步要編譯xml文件為二進制文件,同時生成資源APK环肘。

aapt package -f -M app/src/main/AndroidManifest.xml 
-I android.jar -S app/src/main/res/ -A app/src/main/assets 
-F app/src/main/out/res.apk

這里只是輸出結(jié)果變成了APK欲虚,成功的話在out目錄下會看到res.apk。

9. 把代碼打入到APK里

上一步已經(jīng)生成了資源APK悔雹,但沒有代碼复哆,這一步我們把dex文件和resources打入到APK中。早期是直接使用apkbuilder工具直接打包腌零,但是目前sdk將該工具移除了梯找。其實apkbuilder最終調(diào)用的是sdklib.jar中的com.android.sdklib.build.ApkBuilderMain類來做事情的,所以這里直接通過 java <class地址> 使用ApkBuilderMain這個類莱没,把resources和classes.dex加入到apk文件中初肉。

java -classpath /Users/peizhifei/Library/Android/sdk/tools/lib/sdklib.jar
com.android.sdklib.build.ApkBuilderMain
app/src/main/out/res.apk -v -u -z 
app/src/main/out/resources -f 
app/src/main/build/classes.dex 

成功的話可以打開res.apk,看到dex文件已經(jīng)打進去了饰躲。

10. 簽名APK

apk安裝必須要簽名牙咏,我們使用jarsigner給apk手動簽名,為了方便可以使用debug簽名嘹裂。

jarsigner -verbose -keystore ~/.android/debug.keystore 
-storepass android -keypass android 
app/src/main/out/res.apk androiddebugkey

jarsigner的命令格式是這樣的妄壶;

jarsigner -verbose -keystore <簽名.keystore> -signedjar <簽名ed.apk> <未簽名.apk> <別名>  

11. 對齊優(yōu)化

至此APK就已經(jīng)生成了,可以安裝在手機上了寄狼,但是正常項目還是需要進行對齊優(yōu)化的丁寄,能加快apk解壓速度,需要用到zipalign工具泊愧。

zipalign -f 4 app/src/main/out/res.apk app/src/main/out/res_ zipalign.apk

成功后對齊的apk就是out目錄下res_ zipalign.apk伊磺。

12. 安裝并啟動

這里可以安裝APK到手機并啟動主界面

adb install -r app/src/main/out/res2.apk
adb shell am start -n
com.example.peizhifei.myapplication/.MainActivity

這里用了強制安裝,這樣就能覆蓋安裝删咱。

到此我們就大概實現(xiàn)了apk的打包過程屑埋,當(dāng)然在實際項目中,要比上邊的流程更復(fù)雜寫痰滋,包括多module依賴摘能,so文件引用续崖,代碼混淆等。

最后把所有這些命令都可以統(tǒng)一放到一個shell腳本里去執(zhí)行团搞。
為了路徑簡短严望,我把android.jar放到了app/src/main/下面,并進入到該目錄逻恐,避免每次輸入app/src/main/像吻。

#進入項目目錄
cd app/src/main/

#創(chuàng)建輔助目錄
mkdir -p {gen,build,out}

#生成R文件
aapt p -f  -M AndroidManifest.xml  -I  android.jar -S  res -J gen  -m

#編譯aidl文件
aidl -Iapp/src aidl/com/example/peizhifei/myapplication/IMyAidlInterface.aidl

#編譯得到class文件
javac -source 1.8 -target 1.8 -encoding UTF-8 -bootclasspath android.jar -d build java/com/example/peizhifei/myapplication/*.java gen/com/example/peizhifei/myapplication/*.java aidl/com/example/peizhifei/myapplication/*.java

#缺一步混淆

#將class文件生成dex文件
dx --dex --output=build/classes.dex build/

#生成資源映射表
aapt package -f -M AndroidManifest.xml -I android.jar -S res -A assets -F out/resources

#生成資源和二進制文件
aapt package -f -M AndroidManifest.xml -I android.jar -S res -A assets -F out/res.apk

#把代碼打入到資源里
java -classpath /Users/peizhifei/Library/Android/sdk/tools/lib/sdklib.jar com.android.sdklib.build.ApkBuilderMain out/res.apk -v -u -z out/resources -f build/classes.dex

#簽名APK
jarsigner -verbose -keystore ~/.android/debug.keystore -storepass android -keypass android out/res.apk androiddebugkey

#對齊優(yōu)化
zipalign -f 4 out/res.apk out/res_zipalign.apk

#強制安裝
adb install -r out/res_zipalign.apk

#啟動主界面
adb shell am start -n com.example.peizhifei.myapplication/.MainActivity

直接執(zhí)行該腳本,手機上就會啟動主界面梢莽,簡單總結(jié)一下萧豆。

aapt是一個重要的工具奸披,來生成R.java文件和resource.arsc昏名。assets是不需要做任何處理的,res/raw只需分配id后與assets一起直接打包到應(yīng)用程序中阵面,其它xml文件則會被編譯成二進制文件轻局。編譯過程中,會把xml中的字符串進行收集去重样刷,形成字符串資源池仑扑,元素中用到字符串的地方將被替換成相應(yīng)的索引。另外標(biāo)簽屬性值都會轉(zhuǎn)換為資源id置鼻,進一步減少文件大小镇饮。二進制格式的xml把標(biāo)簽屬性值轉(zhuǎn)換為資源id后,避免了字符串解析箕母,從而提高了解析速度储藐。

另外就是生成資源APK后需要把代碼打入到APK里面,然后對APK做一些優(yōu)化處理即可嘶是。其實這個演示更多是為了加深對編譯過程的理解钙勃,比如插件化處理資源就會從aapt入手解決資源沖突,漢化可以考慮修改resource.arsc并進行二次打包等聂喇。

本文介紹了APK的打包過程辖源,實際操作演示了一下,感謝大家的閱讀希太,我們下周再見克饶。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市誊辉,隨后出現(xiàn)的幾起案子矾湃,更是在濱河造成了極大的恐慌,老刑警劉巖芥映,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件洲尊,死亡現(xiàn)場離奇詭異远豺,居然都是意外死亡,警方通過查閱死者的電腦和手機坞嘀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門躯护,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人丽涩,你說我怎么就攤上這事棺滞。” “怎么了矢渊?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵继准,是天一觀的道長。 經(jīng)常有香客問我矮男,道長移必,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任毡鉴,我火速辦了婚禮崔泵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘猪瞬。我一直安慰自己憎瘸,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布陈瘦。 她就那樣靜靜地躺著幌甘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪痊项。 梳的紋絲不亂的頭發(fā)上锅风,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天,我揣著相機與錄音线婚,去河邊找鬼遏弱。 笑死,一個胖子當(dāng)著我的面吹牛塞弊,可吹牛的內(nèi)容都是我干的漱逸。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼游沿,長吁一口氣:“原來是場噩夢啊……” “哼饰抒!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起诀黍,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤袋坑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后眯勾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體枣宫,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡婆誓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了也颤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片洋幻。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖翅娶,靈堂內(nèi)的尸體忽然破棺而出文留,到底是詐尸還是另有隱情,我是刑警寧澤竭沫,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布燥翅,位于F島的核電站,受9級特大地震影響蜕提,放射性物質(zhì)發(fā)生泄漏森书。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一贯溅、第九天 我趴在偏房一處隱蔽的房頂上張望拄氯。 院中可真熱鬧,春花似錦它浅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至典唇,卻和暖如春镊折,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背介衔。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工恨胚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人炎咖。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓赃泡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親乘盼。 傳聞我的和親對象是個殘疾皇子升熊,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 1.使用aapt打包res資源文件,生成R.java绸栅,resources.arsc(資源映射信息)以及其他re?s...
    舌尖上的Android閱讀 722評論 0 0
  • 概述Apk其實是一個壓縮包级野,當(dāng)解壓后,其內(nèi)部主要就是資源文件和classes.dex粹胯。這個classes.dex文...
    breaktian閱讀 653評論 0 1
  • 在《Android軟件安全與逆向分析》書中看到android apk的打包過程蓖柔,覺得比較有意思辰企,因此根據(jù)書中內(nèi)容整...
    chichichichi閱讀 2,630評論 0 4
  • Android 官方配置構(gòu)建介紹aapt命令介紹參考老羅的文章 再來一張詳細的圖 aapt打包過程 1. 解析An...
    第八區(qū)閱讀 444評論 0 2
  • Apk的打包,大致就是把代碼打成包况鸣、把資源打成包蟆豫、最后對整個Apk文件做一下安全處理和優(yōu)化操作,Andriod提供...
    藍灰_q閱讀 397評論 0 2