Android專案的依賴關係解析

codeceo發表於2015-03-23

在Android SDK Tools和Eclipse ADT 外掛的第17版本 (revision 17)中,我們對Android專案的依賴關係管理做了很多改變。

我們所做的第一個改變是調整基於 Ant 的編譯系統和 Eclipse ADT 外掛,使他們具有相同的行為。

Android 專案包含原始碼資料夾,以及對庫專案 (android library projects) 和 jar 檔案的依賴。 不需要其他多餘的設定,只需要在project.properties中新增對於庫專案的依賴,Android專案就會在動在 classpath 中新增以下依賴項:

  • libs/*.jar 的內容
  • 庫專案(library project)的輸出。
  • 庫專案的 libs/*.jar 的內容。

這些依賴項,加上專案自身原始碼編譯的結果,被一起交給DEX工具,然後被轉化成位元組碼從而打包到最終的APK當中。

因為一個專案可能依賴於好幾個使用相同的 jar 檔案的庫專案,Android 編譯系統會檢查所有所需的 jar 檔案,檢測出來自不同的庫專案的重複 jar 檔案,並刪除這些重複的jar引用。這會防止可怕的”already added” DX錯誤。

下面介紹了系統如何發現重複引用。

重要的變化 我們已經改變了庫專案生成和打包R類的方式:

  • R類不再被打包到庫專案的輸出 jar 包中。
  • 庫專案不再為其所依賴的庫專案生成R類。 只有主應用專案才會在生成本身R類的同時為所依賴的庫專案生成R類。

這意味著庫專案不能匯入(import)另一個庫專案的R類。 其實這是沒有必要的,因為它們自身的R類包含所有必要的資源。

請注意,應用程式的專案仍然可以匯入所引用的庫專案的R類,但是重申一遍,其實沒有必要這麼做, 因為他們本身的R類包括所有的資源。

Eclipse的具體變化

由於不光包含庫專案,被稱為”Library Projects”的動態class path容器 (dynamic class path container) 已更名為“Android Dependancies”。

現在被庫專案引用的純 Java 專案也可以填充classpath容器。 如果這些Java專案也引用其他 Java 專案或 jar 檔案,它們將被自動新增(現在也支援通過 user libraries引用的jar檔案)。

重要: 僅當被引用的項被標記為”exported”時這才起作用。 請注意,預設情況下,當一個專案或jar檔案被新增到專案的build path 中時是不會被標記為”exported”。

庫專案( 以及它們所引用的lib/*.jar檔案)總是會被標記為”exported”。

重要: 如果你還在手動引用jar類庫,而不是把他們放在libs目錄下, 注意以下幾點:

  • 如果該專案是一個 library project,應用專案預設情況下看不見這些jar 類庫。 你必須把這些類庫挪到”libs”子目錄下。
  • 如果該專案是一個應用程式專案,你可以這樣做,但你必須確保把引用的jar檔案標記為”exported”。

下圖介紹瞭如何將Java專案和jar類庫標記為”exported”(Android Dependencies 容器不必被標為”exported”,反正它總是會被匯出):

Mark references as exported in Eclipse

再次強調一下, 重複的引用(包括引用的專案和 jar 檔案)會被自動發現並且刪除掉。

依賴解析

當一個專案引用了兩個庫專案,都需要相同的jar檔案,編譯系統需要檢測和解決這種重複。

一個完整的依賴系統會將每個jar檔案關聯到一個完全限定名 (fully qualified name) 和一個版本號,以決定使用哪個版本。

不幸的是,Android編譯系統暫時還沒有一個完整的依賴解析系統。 在此期間,我們按照下列規則實現了一個簡單的系統:

** 嚴格按照檔名來識別 jar 檔案 **

這意味著 mylib.jar 和 mylib-v2.jar 是不同的兩個檔案,雖然它們實際上是不同版本的同一個類庫, 他們都將被打包,從而可能導致 dx “already added” 錯誤。

對於具有相同檔名的 jar 檔案,“相同版本”是指完全相同的檔案。

目前,我們的檢測是非常基本的,只檢查這些檔案是不是有相同的大小和sha1 值。

如果兩個庫都包含在他們的libs資料夾名為mylib.jar檔案,但是這兩個檔案是不同的,編譯系統將不能指出這種依賴錯誤。

解決的辦法: 如果它們是相同的類庫,確保兩個jar檔案實際上是同一個。 如果是不同的兩個類庫,把他們重新命名為不同的jar包。

特殊情況: android-support-v4.jar 和 android-support-v13.jar

我們把這兩個庫當作特殊情況來處理, 因為-V13裡面包含一個完整-V4的版本。 如果發現兩者同時存在,只有V13被使用。

請注意,我們不能保證-V13中使用的-V4版本和其他老的類庫使用到的-V4版本是相同的。 我們建議,當您更新您的專案與新版本的support library,你在同一時間更新您的所有專案,無論他們使用-V4還是-V13。

相關文章