參考文章?https://wetest.qq.com/lab/view/324.html
分成以下四個(gè)部分:
? ? Unity工程中的Plugin/Android文件夾
? ??Android打包工具
? ??如何把上述個(gè)文件夾打包到APK文件的
? ??APK中的assets\bin\Data文件夾
Unity工程中的Plugin/Android文件夾
先介紹一下Unity打包apk的重要文件夾Plugin/Android,下面是某個(gè)項(xiàng)目中的Plugin/Android文件夾根目錄:

1. 紅框部分是一個(gè)Android工程的常規(guī)目錄:libs、res、assets文件夾以及AndroidManifest.xml文件
2. GCloudVoice?和?resProject?文件夾是我們引用的第三方庫(kù),他們也會(huì)被打包到APK中,文件夾里面的目錄里結(jié)構(gòu)也是Android工程的一些常規(guī)目錄:


特別注意?project.properties文件一般只有在庫(kù)項(xiàng)目里面能看得到,里面的內(nèi)容極少,一般就只有一句話android.library=true。有了這句話里面的東西才會(huì)被打包進(jìn)apk中。否則就不會(huì)認(rèn)為這個(gè)文件夾里面是個(gè)Android的庫(kù)項(xiàng)目,整個(gè)文件夾都將被忽略,不要忘了寫(xiě)。
3.?cos.aar?和?TakePhoto.aar?也是兩個(gè)庫(kù)文件(可以查看文章Android中的AAR包),解壓可以查看內(nèi)容,是一個(gè)Android庫(kù)工程。
4. 那兩個(gè)AndroidMannifest_xxxx.xml(AndroidMannifest-CellphoneCollector.xml 和 AndroidMannifest-ImagePickerRes.xml) 不知道干啥的,還沒(méi)搞明白,估計(jì)沒(méi)用?
5. UnityWebView.jar?jar包? 直接放在了外面jar包,會(huì)跟根目錄下libs文件夾下的jar包一起打包到classes.dex里面的(下面會(huì)介紹classes.dex)。除了Plugin/Android文件夾下的jar包外,Unity打包的時(shí)候還會(huì)引入自己的Android的jar包——classes.jar,里面包含了Unity需要的庫(kù)類,關(guān)鍵類UnityPlayerActivity就是Android程序的默認(rèn)入口類。classes.jar的位置在:Windows:Unity\Editor\Data?以及? Mac:/Applications/Unity?的以下三個(gè)文件夾中均有一份:
C:\unity5\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Development\Classes
C:\unity5\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\il2cpp\Development\Classes
C:\unity5\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes
Android打包工具
Android提供了一個(gè)叫做aapt的工具(可以查看文章Android打包工具aapt),Unity構(gòu)建apk的時(shí)候需要androidsdk和jdk路徑的(可以查看文章打包android的設(shè)置),而aapt就是在androidsdk目錄下(我的C:\Android\android-sdk\build-tools\28.0.3),這個(gè)工具完成了上述大部分的對(duì)資源文件處理的工作。
除了aapt,還有其他的Android提供的工具鏈(Android Build Tools),都在build-tools目錄下,Unity通過(guò)對(duì)Android提供的工具鏈的一系列調(diào)用從而完成打包APK的操作。可以當(dāng)作Unity寫(xiě)了個(gè)bat/bash腳本,這個(gè)腳本按照順序調(diào)用Android提供的工具來(lái)完成打包APK(常見(jiàn)的Android IDE里面,這樣的“bat/bash腳本”往往是一個(gè)完整的構(gòu)建系統(tǒng),比如Eclipse?用的Ant,Android Studio?IDE用的gradle)。
如何把上述個(gè)文件夾打包到APK文件的
Unity打包apk的注意過(guò)程把libs、res、assets文件夾以及AndroidManifest.xml文件這些內(nèi)容以固定的方式組織起來(lái)壓縮到APK文件里面(包括第三方庫(kù)中的這幾個(gè)文件夾)
可以先了解下apk下都是什么目錄結(jié)構(gòu)(查看文章APK直接解壓看內(nèi)容?和 APK的反編譯方法)
1.libs文件夾?————》 .jar打包成classes.dex,.so文件不打包。
libs文件夾里面有很多.jar文件,以及三個(gè)文件夾armeabi,armeabi-v7a,x86:

*.jar文件——.jar是Java編譯器把.java代碼編譯后的文件。這里用的jar包一般是由其他Android的IDE生成完成后再拷貝過(guò)來(lái)的。Android在打包的時(shí)候會(huì)把項(xiàng)目里面的所有jar文件進(jìn)行一次合并、壓縮、重新編譯變成classes.dex文件被放在APK根目錄下。當(dāng)應(yīng)用被執(zhí)行的時(shí)候Android系統(tǒng)內(nèi)的Java虛擬機(jī)(Dalvik或者Art),會(huì)去解讀classes.dex里面的字節(jié)碼并且執(zhí)行??傊褪前驯姸鄇ar包編譯成classes.dex文件。
armeabi-v7a、armeabi、x86等幾個(gè)固定的文件夾——里面存放的同樣名字的so文件,是針對(duì)不同的CPU架構(gòu)生成的*.so文件。so是動(dòng)態(tài)庫(kù)文件,直接放在APK根目錄下的lib目錄下的對(duì)應(yīng)的文件夾中。(查看文章Android中的so文件)
2.assets文件夾————》原封不動(dòng)的被拷貝到APK根目錄下的assets文件夾
這些文件里面的內(nèi)容不會(huì)在R文件注冊(cè)。這個(gè)文件夾有幾個(gè)特性。
√ 里面的文件基本不會(huì)被Android的打包工具修改,應(yīng)用里面要用的時(shí)候可以讀出來(lái)。
√ 打出包以后,這個(gè)文件夾是只讀的,不能修改。
√ 讀取這個(gè)文件夾里面的內(nèi)容的時(shí)候要通過(guò)特定的Android API來(lái)讀取,參考getAssets()。
√ 基于上述兩點(diǎn),在Unity中,要讀取這部分內(nèi)容要通過(guò)WWW來(lái)進(jìn)行加載。
除此之外,最終apk中的assets文件夾中還將包括StreamingAssets目錄下的文件(項(xiàng)目打AB包出來(lái)的時(shí)候最終存放AssetBundle包路徑就是:Assets/StreamingAssets,所以這些ab包也是直接放到了apk的assets目錄下。)
該目錄用于存放項(xiàng)目相關(guān)的資源文件,這個(gè)目錄和res包含的xml文件差不多,也是應(yīng)用中引用到的一些外部資源。但主要區(qū)別在于這些資源是以原始格式保存,且只能用編程方式讀取。例如文本文件,視頻文件,MP3音頻等媒體文件。
3.res文件夾————》xml文件轉(zhuǎn)化為二進(jìn)制格式,其他一般不處理;生成資源映射文件resources.arsc;目錄結(jié)構(gòu)不變存放APK根目錄下的res文件夾中
存放的是xml文件以及一些圖片素材文件??梢韵攘私庖幌?b>文章Android工程的資源管理。

1. xml文件在被打包的時(shí)候會(huì)被轉(zhuǎn)換成一種讀取效率更高的一種特殊格式(也是二進(jìn)制的格式,所以直接解壓出來(lái)看是亂碼了),命名的時(shí)候還是以xml為結(jié)尾被放到APK包里面的res文件夾下,其目錄結(jié)構(gòu)會(huì)跟打包之前的目錄結(jié)構(gòu)相對(duì)應(yīng)。xml文件一般來(lái)說(shuō)有以下幾種:
? ??layout文件夾——布局文件,文件里描述的一般都是原生界面的布局信息。(Unity游戲的顯示是直接通過(guò)GL渲染指令來(lái)完成的,一般不會(huì)涉及到這些文件。但是在接sdk的時(shí)候會(huì)用到。)文件的命名規(guī)范全部小寫(xiě),采用下劃線命名,一般按照組件名_功能名_屬性名方式,具備較高的可讀性。如:activity_login,fragment_constact_child(某個(gè)ConstactFragment類中的child視圖)。這樣規(guī)范命名的話,在Activity的onCreate中使用R.layout.的時(shí)候就只需篩選activity開(kāi)頭的xml文件;在Fragment的onCreateView中使用R.layout.的時(shí)候就只需篩選fragment開(kāi)頭的xml文件,
? ??values文件夾——字符串定義文件,key-value對(duì),定義一些字符串,方便程序做國(guó)際化還有本地化用(XX_strings.xml)。還有一些其他的顏色(XX_color.xml)、度量(XX_dimens.xml)等,還有其他xml會(huì)引用到的字符串,一般常見(jiàn)的是app的名稱。
? ??動(dòng)畫(huà)文件,一般定義的是Android原生界面元素的動(dòng)畫(huà),對(duì)于Unity游戲,我們一般也不會(huì)涉及他。
? ? 其他目錄下的xml文件,如上面的xml?和?color
2.建立res文件夾下的資源文件跟代碼靜態(tài)引用到的資源文件的映射,放到APK根目錄的resources.arsc文件。所以在打包后的比如xml中的資源路徑相關(guān)的配置由原來(lái)的可讀路徑都變成了id值。
3.圖片資源——在打包過(guò)程中會(huì)被放到APK的對(duì)應(yīng)文件夾內(nèi)的對(duì)應(yīng)目錄
drawable為開(kāi)頭的文件夾——圖片資源,用于存儲(chǔ).png、.9.png、.jpg等圖片資源(.9.png是Android特有的圖片格式,可以根據(jù)情況進(jìn)行拉伸,達(dá)到不變形的效果),后綴一般會(huì)根據(jù)手機(jī)的像素密度來(lái)來(lái)進(jìn)行區(qū)分,這樣我們可以往這些文件夾內(nèi)放入對(duì)應(yīng)像素密度的圖片資源。后綴為ldpi的drawable文件夾里面的圖片的尺寸一般來(lái)說(shuō)會(huì)是整個(gè)系列里面最小的,因?yàn)檫@個(gè)文件夾的內(nèi)容會(huì)被放到像素密度最低的那些手機(jī)上運(yùn)行。而一般1080p或者2k甚至4k的手機(jī)在讀取圖片的時(shí)候會(huì)從后綴為xxxxhdpi的文件夾里面去讀,這樣才可以保證應(yīng)用內(nèi)的圖像清晰。
4.其他資源——直接存放到對(duì)應(yīng)目錄下
raw文件夾——用于存放應(yīng)用程序所用到的聲音比如wav等資源。raw中的文件會(huì)被映射到R.java文件中,訪問(wèn)的時(shí)候直接使用資源ID即R.id.filename;而如果是放到assets文件夾下,則不會(huì)被映射到R.java中,訪問(wèn)的時(shí)候需要AssetManager類。
以上的資源由于有資源映射,所以最終只有在程序中用到的資源文件才會(huì)被打包進(jìn)最終的apk中。
4.AndroidManifest.xml————》各個(gè)文件夾或者包中的AndroidManifest.xml合并成一個(gè)存放APK根目錄下
在Android系統(tǒng)安裝以及啟動(dòng)應(yīng)用的時(shí)候,會(huì)首先來(lái)讀取AndroidManifest.xml這個(gè)文件的內(nèi)容,分析出這個(gè)應(yīng)用分別使用了那些基本的元素,以及應(yīng)該從classes.dex文件內(nèi)讀取哪一段代碼來(lái)使用,應(yīng)該往桌面上放哪個(gè)圖標(biāo),這個(gè)應(yīng)用能不能被拿來(lái)debug等等。
打包工具在處理Unity項(xiàng)目里面的AndroidManifest文件時(shí)會(huì)將所有AndroidManifest文件的內(nèi)容合并到一起,也就是說(shuō)主項(xiàng)目引用到的庫(kù)項(xiàng)目里面如果也有AndroidManifest文件,都會(huì)被合并到一起。這樣就不需要手動(dòng)復(fù)制粘貼。需要說(shuō)明的是,這份文件在打包Android程序的時(shí)候是必不可少的,但是在Unity打包的時(shí)候,他會(huì)先檢查Plugins目錄下有沒(méi)有這份文件,如果沒(méi)有就會(huì)用一個(gè)自帶的AndroidManifest來(lái)代替。此外,Unity還會(huì)自動(dòng)檢查項(xiàng)目中AndroidManifest里面的某些信息是不是默認(rèn)值,如果是的話,會(huì)拿Unity項(xiàng)目中的值來(lái)進(jìn)行替換。例如,游戲的App名稱以及圖標(biāo)等。
如果在Plugins/Android,不存在AndroidManifest文件,會(huì)使用Unity默認(rèn)的AndroidManifest文件。默認(rèn)的AndroidManifest文件目錄在:Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Apk
關(guān)于AndroidManifest.xml具體內(nèi)容可以查看這篇文章。
APK中的assets\bin\Data文件夾
最終打出來(lái)apk中的assets文件夾的內(nèi)容除了之前說(shuō)的Plugin/Android/下的assets,以及Unity工程下StreamingAssets外,還有一個(gè)bin文件夾,下面看看內(nèi)容:
bin\Data這里存放的是Unity的代碼資源,場(chǎng)景資源,和比如Resource文件夾下面的資源。下面是一個(gè)簡(jiǎn)單的demo工程,只包含一個(gè)場(chǎng)景,就是level0,Assembly-CSharp.dll庫(kù)就是C#代碼邏輯。(這里面的dll還有待仔細(xì)看,還不是很懂都是干嘛的)

在一些大的工程中打包成apk后,assets\bin\Data目錄下看到大量的文件名很長(zhǎng)而且無(wú)意義的文件,這些就是Unity中的Resources目錄下的資源。當(dāng)打包成APK發(fā)布的時(shí)候,Unity把這些資源全都打散了,然后把資源的文件名都變成了上圖中顯示的文件Hash值:
