Unity是怎麼打包APK文件的

大家看過一些第三方組件的接入文檔都知道,在Unity裏面有幾個特殊的文件夾是跟打包APK有關的。首先我們就來了解一下,這些文件夾裏面的內容是經歷了哪些操作才被放到APK裏面的呢?

在Unity的Assets目錄下,Plugins/Android無疑是其中的重中之重,首先我們先來看一個常見的Plugins/Android目錄是什麼樣子的。

-Android

-- ApolloBase

-- ApolloPlugins

-- assets

-- libs

-- res

-- AndroidManifest.xml

後面的四個是Android工程的文件。前面兩個文件夾是我們引用的第三方庫,他們也會被打包到APK中。我們這個時候如果點進去前兩個文件夾,我們會發現他們的目錄結構跟Android這個目錄也很像,大概是一下這個樣子的。

-ApolloPlugins

-- libs

-- res

-- AndroidManifest.xml

-- project.properties

比較上下兩層的目錄接口我們可以發現有很多相似的部分,如:libs、res、assets文件夾以及AndroidManifest.xml文件。這些其實都是一個標準的Android項目的所需要的文件。Unity自帶的Android打包工具的作用就是把上述這幾個文件夾裏面的內容以固定的方式組織起來壓縮到APK文件裏面。

接下來我們分別來看看Android打包工具都會做什麼樣的操作。

● libs文件夾裏面有很多.jar文件,以及被放在固定名字的文件夾裏面的.so文件。*.jar文件是Java編譯器把.java代碼編譯後的文件,Android在打包的時候會把項目裏面的所有jar文件進行一次合併、壓縮、重新編譯變成classes.dex文件被放在APK根目錄下。當應用被執行的時候Android系統內的Java虛擬機(Dalvik或者Art),會去解讀classes.dex裏面的字節碼並且執行。把衆多jar包編譯成classes.dex文件是打包Android應用不可或缺的一步。

看到這裏有人可能會想不對啊,這一步只將jar包打成dex文件,那之前的java文件生成jar文件難道不是在這一步做嗎?沒錯,這裏用的jar包一般是由其他Android的IDE生成完成後再拷貝過來的。本文後面的部分會涉及到怎麼使用Android的IDE並且生成必要的文件。

● libs文件夾的*.so文件則是可以動態的被Android系統加載的庫文件,一般是由C/C++撰寫而成然後編譯成的二進制文件。要注意的是,由於實際執行這些二進制庫的CPU的架構不一樣,所以同樣的CC++代碼一般會針對不同的CPU架構生成幾分不同的文件。這就是爲什麼libs文件夾裏面通常都有armeabi-v7a、armeabi、x86等幾個固定的文件夾,而且裏面的.so文件也都是有相同的命名方式。Java虛擬機在加載這些動態庫的時候會根據當前CPU的架構來選擇對應的so文件。有時候這些so文件是可以在不同的CPU架構上執行的,只是在不對應的架構上執行速度會慢一些,所以當追求速度的時候可以給針對每個架構輸出對應的so文件,當追求包體大小的時候輸出一個armeabi的so文件就可以了。

● assets文件夾,這個裏面的東西最簡單了,在打包APK的時候,這些文件裏面的內容會被原封不動的被拷貝到APK根目錄下的assets文件夾。這個文件夾有幾個特性。

√ 裏面的文件基本不會被Android的打包工具修改,應用裏面要用的時候可以讀出來。

√ 打出包以後,這個文件夾是隻讀的,不能修改。

√ 讀取這個文件夾裏面的內容的時候要通過特定的Android API來讀取,參考getAssets()。

√ 基於上述兩點,在Unity中,要讀取這部分內容要通過WWW來進行加載。

除了Plugins/Android內的所有assets文件夾裏面的文件會連同StreamingAssets目錄下的文件一起被放到APK根目錄下的assets文件夾。

● res文件夾裏面一般放的是xml文件以及一些圖片素材文件。xml文件一般來說有以下幾種:

√ 佈局文件,被放在res中以layout開頭的文件夾中,文件裏描述的一般都是原生界面的佈局信息。由於Unity遊戲的顯示是直接通過GL指令來完成的,所以我們一般不會涉及到這些文件。

√ 字符串定義文件,一般被放到values文件夾下,這個裏面可以定義一些字符串在裏面,方便程序做國際

化還有本地化用。當然有時候被放到裏面的還有其他xml會引用到的字符串,一般常見的是app的名稱。

√ 動畫文件,一般定義的是Android原生界面元素的動畫,對於Unity遊戲,我們一般也不會涉及他。

√ 圖片資源,一般放在以drawable爲開頭的文件夾內。這些文件夾的後綴一般會根據手機的像素密度來來進行區分,這樣我們可以往這些文件夾內放入對應像素密度的圖片資源。

例如後綴爲ldpi的drawable文件夾裏面的圖片的尺寸一般來說會是整個系列裏面最小的,因爲這個文件夾的內容會被放到像素密度最低的那些手機上運行。而一般1080p或者2k甚至4k的手機在讀取圖片的時候會從後綴爲xxxxhdpi的文件夾裏面去讀,這樣纔可以保證應用內的圖像清晰。圖片資源在打包過程中會被放到APK的res文件夾內的對應目錄。

√ Android還有其他一些常見的xml文件,這裏就不一一列舉了。

res文件夾下的xml文件在被打包的時候會被轉換成一種讀取效率更高的一種特殊格式(也是二進制的格式),命名的時候還是以xml爲結尾被放到APK包裏面的res文件夾下,其目錄結構會跟打包之前的目錄結構相對應。

除了轉換xml之外,Android的打包工具還會把res文件夾下的資源文件跟代碼靜態引用到的資源文件的映射給建立起來,放到APK根目錄的resources.arsc文件。這一步可以確保安卓應用啓動的時候可以加載出正確的界面,是打包Android應用不可或缺的一步。

● AndroidManifest.xml,這份文件太重要了,這是一份給Android系統讀取的指引,在Android系統安裝、啓動應用的時候,他會首先來讀取這個文件的內容,分析出這個應用分別使用了那些基本的元素,以及應該從classes.dex文件內讀取哪一段代碼來使用又或者是應該往桌面上放哪個圖標,這個應用能不能被拿來debug等等。在後面的部分會有詳細解釋。打包工具在處理Unity項目裏面的AndroidManifest文件時會將所有AndroidManifest文件的內容合併到一起,也就是說主項目引用到的庫項目裏面如果也有AndroidManifest文

件,都會被合併到一起。這樣就不需要手動複製粘貼。需要說明的是,這份文件在打包Android程序的時候是必不可少的,但是在Unity打包的時候,他會先檢查Plugins目錄下有沒有這份文件,如果沒有就會用一個自帶的AndroidManifest來代替。此外,Unity還會自動檢查項目中AndroidManifest裏面的某些信息是不是默認值,如果是的話,會拿Unity項目中的值來進行替換。例如,遊戲的App名稱以及圖標等。

● project.properties,這份文件一般只有在庫項目裏面能看得到,裏面的內容極少,就只有一句話android.library=true。但是少了這份文件Android的打包工具就不會認爲這個文件夾裏面是個Android的庫項目,從而在打包的時候整個文件夾會被忽略。這有時候不會影響到打包的流程,打包過程中也不會報錯,但是打出的APK包缺少資源或者代碼,一跑就崩潰。關於這份文件,其實在Unity的官方文檔上並沒有詳細的描述(因爲他實際上是Android項目的基礎知識),導致很多剛剛接觸Unity-Android開發的開發者在這裏栽坑。曾

經有個很早就開始用Unity做Android遊戲的老前輩告訴我要搞定Unity中的Android庫依賴的做法是用Eclipse打開Plugins/Android文件夾,把裏面的所有的項目依賴處理好就行了。殊不知這樣將Unity項目跟Eclipse項目耦合在一起的做法是不太合理的,會造成Unity項目開啓的時候緩慢。

● 其他文件夾例如aidl以及jni在Unity生成APK這一步一般不會涉及到,這裏不展開。

看到了上述介紹的Unity打包APK的基礎知識我們知道了往Plugins/Android目錄下放什麼樣的文件會對APK包產生什麼樣的影響。但是實際上上述的內容只是着重的講了Unity是怎麼打包APK,所以接下來會簡述一下打包這個步驟到底是怎麼完成的。

Android提供了一個叫做aapt的工具,這個工具的全稱是Android Asset Packaging Tool,這個工具完成了上述大部分的對資源文件處理的工作,而Unity則是通過對Android提供的工具鏈(Android Build Tools)的一系列調用從而完成打包APK的操作。這裏感覺有點像我們寫了個bat/bash腳本,這個腳本按照順序調用Android提供的工具一樣。在一些常見的Android IDE裏面,這樣的“bat/bash腳本”往往是一個完整的構建系統。最早的Android IDE是Eclipse,他的構建系統是Ant,是基於XML配置的構建系統。後來Android團隊推出了Android專用的IDE——Android Studio(這個在文章後面會有詳述),他的構建系統則是換成了gradle,從基於xml的配置一下子升級到了語言(DSL, Domain Specific Language)的層級,給使用Android Studio的人帶來更多的彈性。

寫到這裏我想很多人都清楚了要怎麼把Android的SDK/插件放到Unity裏面並且打包到Unity裏面。這時候應該有人會說,光會放這些文件不夠啊,我還需要知道自己怎麼寫Android的代碼並且輸出相應的SDK/插件給Unity使用啊。

更多unity2018的功能介紹請到paws3d爪爪學院查找。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章