Android 庫的結構與 Android 應用模塊的結構相同。它可以提供構建應用所需的一切內容,包括源代碼、資源文件和 Android 清單。不過,Android 庫將編譯爲您可以用作 Android 應用模塊依賴項的 Android ARchive (AAR) 文件,而不是編譯爲在設備上運行的 APK。與 JAR 文件不同,AAR 文件可以包含多項 Android 資源和一個清單文件,讓您除了能夠在 Java 類和方法中進行捆綁以外,還能夠在佈局和可繪製對象等共享資源中進行捆綁。
庫模塊在以下情況下非常有用:
- 當您要編譯多個使用某些相同的組件(例如 Activity、服務或界面佈局)的應用時。
- 當您要編譯存在於多個 AKP 變體中的應用時(例如免費版本和付費版本,並且您需要在這兩個版本中使用相同的核心組件)。
無論在哪種情況下,您都只需將想要重複使用的文件移到庫模塊中,然後將庫添加爲每個應用模塊的依賴項。本頁將向您介紹如何執行這兩個操作。
創建庫模塊
要在您的項目中創建新的庫模塊,請按以下步驟操作:
- 依次點擊 File > New > New Module。
- 在隨即顯示的 Create New Module 窗口中,點擊 Android Library,然後點擊 Next。
還有一個用於創建 Java 庫的選項,它可以編譯傳統的 JAR 文件。雖然 JAR 文件對很多項目(尤其是當您想要與其他平臺共享代碼時)都很有用,但它不允許您包含 Android 資源或清單文件,而要在 Android 項目中重複使用代碼,Android 資源和清單文件是非常有用的。因此,本指南側重於介紹如何創建 Android 庫。
- 爲您的庫命名,併爲庫中的代碼選擇一個最低的 SDK 版本,然後點擊 Finish。
在 Gradle 項目同步完成後,庫模塊會顯示在左側的 Project 面板中。如果您沒有看到新模塊文件夾,請確保其顯示的是 Android 視圖。
將應用模塊轉換爲庫模塊
如果現有的應用模塊包含您想要重複使用的所有代碼,您可以按照以下步驟將其轉換爲庫模塊:
- 打開模塊級
build.gradle
文件。 - 刪除
applicationId
行。只有 Android 應用模塊才能定義此行。 - 在文件的頂部,您應該會看到以下代碼:
apply plugin: 'com.android.application'
將其更改爲以下代碼:
apply plugin: 'com.android.library'
- 保存文件,然後依次點擊 File > Sync Project with Gradle Files。
大功告成。模塊的整個結構仍然相同,但是現在它會作爲 Android 庫運行,編譯現在也會創建 AAR 文件,而不是 APK。
如果您想要編譯 AAR 文件,請在 Project 窗口中選擇庫模塊,然後依次點擊 Build > Build APK。
將庫添加爲依賴項
要在另一個應用模塊中使用您的 Android 庫代碼,請按以下步驟操作:
- 通過以下其中一種方式將相應的庫添加到您的項目(如果庫模塊是您在同一個項目中創建的,那麼它就已經存在於該項目中了,因此您可以跳過此步驟):
- 添加已編譯的 AAR(或 JAR)文件(庫必須已編譯):
- 依次點擊 File > New > New Module。
- 點擊 Import .JAR/.AAR Package,然後點擊 Next。
- 輸入已編譯的 AAR 或 JAR 文件的位置,然後點擊 Finish。
- 將庫模塊導入到您的項目(庫源代碼會成爲項目的一部分):
- 依次點擊 File > New > Import Module。
- 輸入庫模塊目錄的位置,然後點擊 Finish。
此時,庫模塊便複製到您的項目中了,因此您可以實際修改庫代碼。如果您想要維護單個版本的庫代碼,那麼您或許不應該執行此操作,而是應該添加已編譯的 AAR 文件(如上所述)。
- 添加已編譯的 AAR(或 JAR)文件(庫必須已編譯):
- 確保庫列在
settings.gradle
文件的頂部,如下面名爲“my-library-module”的庫所示:include ':app', ':my-library-module'
- 打開應用模塊的
build.gradle
文件,然後將一行新代碼添加到dependencies
塊,如以下代碼段所示:dependencies { implementation project(":my-library-module") }
- 點擊 Sync Project with Gradle Files。
在以上示例中,implementation
配置會將名爲 my-library-module
的庫添加爲整個應用模塊的編譯依賴項。而如果只想將此庫用於特定的編譯變體,您應該使用 buildVariantNameImplementation
,而不是 implementation
。例如,如果您只想在“pro”產品變種中包含此庫,則所需代碼如下所示:
productFlavors {
pro { ... }
}
dependencies {
proImplementation project(":my-library-module")
}
您的應用模塊現在可以訪問 Android 庫中的任何代碼和資源,並且庫 AAR 文件在編譯時已捆綁到您的 APK 中。
不過,如果希望單獨共享 AAR 文件,則可以在 project-name/module-name/build/outputs/aar/
中找到它,也可以通過依次點擊 Build > Make Project 的方式重新生成此文件。
注意:要詳細瞭解依賴項管理,請參閱使用變體感知依賴項管理。
選擇要設爲公開的資源
庫中的所有資源在默認情況下均處於公開狀態。要將所有資源隱式設爲私有,您必須至少將一個特定屬性定義爲公開。資源包括您項目的 res/
目錄中的所有文件,例如圖像。要防止庫的用戶訪問僅供內部使用的資源,您應該通過聲明一個或多個公開資源的方式來使用這種自動私有標識機制。或者,您也可以通過添加空的 <public />
標記將所有資源設爲私有,此標記不會將任何資源設爲公開,而是會將一切(所有資源)都設爲私有。
要聲明公開資源,請向庫的 public.xml
文件添加 <public>
聲明。如果您之前未添加過公開資源,則需要在庫的 res/values/
目錄中創建 public.xml
文件。
以下示例代碼會創建兩個名稱分別爲 mylib_app_name
和 mylib_public_string
的公開字符串資源:
<resources>
<public name="mylib_app_name" type="string"/>
<public name="mylib_public_string" type="string"/>
</resources>
如果想要讓任何資源對使用您的庫的開發者可見,您應該將這些資源設爲公開。
通過將屬性隱式設爲私有,您不僅可以防止庫的用戶從內部庫資源獲得代碼補全建議,還可以重命名或移除私有資源,而不會破壞庫的客戶端。系統會從代碼補全中過濾掉私有資源,並且 Lint 會在您嘗試引用私有資源時發出警告。
在編譯庫時,Android Gradle 插件會獲取公開資源定義,並將其提取到 public.txt
文件中,然後系統會將此文件打包到 AAR 文件中。
庫模塊開發注意事項
在開發庫模塊和相關應用時,請注意以下行爲和限制。
向 Android 應用模塊添加對庫模塊的引用後,您可以設置它們的相對優先級。在編譯時,庫會按照優先級由低到高的順序逐一與應用合併。
-
資源合併衝突
編譯工具會將庫模塊中的資源與相關應用模塊的資源合併。如果這兩個模塊中都定義了給定的資源 ID,系統會使用應用中的資源。
如果多個 AAR 庫之間發生衝突,系統會使用依賴項列表中首先列出的庫(靠近
dependencies
塊頂部)中的資源。爲了避免常用的資源 ID 發生資源衝突,請考慮使用對模塊具有唯一性(或在所有項目模塊之間具有唯一性)的前綴或其他一致的命名方案。
-
在多模塊編譯中,系統會將 JAR 依賴項視爲傳遞依賴項
在向輸出 AAR 的庫項目添加 JAR 依賴項時,JAR 會由庫模塊進行處理,並與其 AAR 打包在一起。
不過,如果您的項目包含庫模塊,並且此模塊已被應用模塊使用,應用模塊便會將庫的本地 JAR 依賴項視爲傳遞依賴項。在這種情況下,本地 JAR 將由使用它的應用模塊進行處理,而不是由庫模塊進行處理。這是爲了加快庫代碼更改導致的增量編譯的速度。
由本地 JAR 依賴項導致的所有 Java 資源衝突都必須在使用相應庫的應用模塊中解決。
-
庫模塊可以依賴於外部 JAR 庫
您可以開發一個依賴於外部庫(例如 Google 地圖外部庫)的庫模塊。在這種情況下,相關應用必須針對包含此外部庫的目標(例如 Google API 插件)進行編譯。另外也要注意,庫模塊和相關應用都必須在其清單文件的
<uses-library>
元素中聲明外部庫。 -
應用模塊的
minSdkVersion
必須等於或大於庫定義的版本庫是作爲相關應用模塊的一部分進行編譯的,因此,庫模塊中使用的 API 必須與應用模塊支持的平臺版本兼容。
-
每個庫模塊都會創建自己的 R 類
在您編譯相關應用模塊時,庫模塊會先編譯到 AAR 文件中,然後再添加到應用模塊中。因此,每個庫都有自己的
R
類,並根據庫的軟件包名稱命名。所需的所有軟件包中都會創建從主模塊和庫模塊生成的R
類,包括主模塊的軟件包和庫的軟件包。 -
庫模塊可以包含自己的 ProGuard 配置文件
如果有用於編譯和發佈 AAR 的庫項目,您可以向庫的編譯配置添加 ProGuard 配置文件,並且 Android Gradle 插件規則適用於您指定的 ProGuard 規則。編譯工具會將此文件嵌入到爲庫模塊生成的 AAR 文件中。在您將庫添加到應用模塊後,庫的 ProGuard 文件會附加到應用模塊的 ProGuard 配置文件 (
proguard.txt
)。通過將 ProGuard 文件嵌入到庫模塊中,您可以確保依賴於相應庫的應用模塊不必手動更新其 ProGuard 文件即可使用此庫。當 Android Studio 編譯系統編譯您的應用時,它會同時使用來自應用模塊和庫的指令。因此無需按照單獨的步驟在庫上運行代碼壓縮器。
要向庫項目添加 ProGuard 規則,您必須使用庫的
build.gradle
文件的defaultConfig
塊內的consumerProguardFiles
屬性指定文件名稱。例如,以下代碼段會將lib-proguard-rules.txt
設爲庫的 ProGuard 配置文件:android { defaultConfig { consumerProguardFiles 'lib-proguard-rules.txt' } ... }
不過,如果庫模塊是要編譯到 APK 中的多模塊編譯的一部分,並且不會生成 AAR,您應該只在使用相應庫的應用模塊上運行代碼縮減。要詳細瞭解 ProGuard 規則及其用法,請參閱壓縮、混淆和優化應用。
-
測試庫模塊的方法與測試應用的方法相同
主要區別在於,庫及其依賴項會作爲測試 APK 的依賴項自動包含在內。這意味着測試 APK 不僅包含自己的代碼,還包含庫的 AAR 及其所有依賴項。由於沒有單獨的“被測應用”,因此
androidTest
任務只會安裝(和卸載)測試 APK。在合併多個清單文件時,Gradle 會遵循默認的優先級順序,並將庫的清單合併到測試 APK 的主清單中。
AAR 文件詳解
AAR 文件的文件擴展名爲 .aar
,Maven 工件類型應該也是 aar
。此文件本身是一個 zip
文件,其中包含以下強制性條目:
/AndroidManifest.xml
/classes.jar
/res/
/R.txt
/public.txt
此外,AAR 文件可能包含以下一個或多個可選條目:
/assets/
/libs/name.jar
/jni/abi_name/name.so
(其中 abi_name 是 Android 支持的 ABI 之一)/proguard.txt
/lint.jar
/api.jar