原文:Create an Android Library
https://developer.android.com/studio/projects/android-library.html
Android library 結構上與 Android 應用模塊(app module) 相同。它可以包含構建應用所必需的一切,包括源碼(source code)、資源文件(resource files)和清單(Android manifest)。然而 Android library 可以被編譯成 AAR(Android Archive) 文件被 Android 應用模塊 依賴,卻不能被編譯成APK在設備上運行。
庫模塊(library module)在下列情況下有用:
- 當你創建的多個應用使用了相同組件,比如 activities、services、UI layouts。
- 當你創建的一個應用存在多個需要相同核心組件的APK版本,比如免費版與付費版。
這兩種情況下,簡單的移動你想重用的文件到一個庫模塊中然后添加這個庫模塊作為各個應用模塊的依賴。本文將教你怎樣做。
創建一個庫模塊
- 點擊 File > New > New Module.
- 在 Create New Module 窗口中,點擊 Android Library,然后點擊 Next。
另一選擇是創建一個 Java Library ,它會構建一個傳統的 JAR 文件。
JAR 文件對許多項目有用,特別是當你想在不同的平臺分享代碼時,但它不能包含對 Android 項目代碼重用有益的資源或清單(manifest)文件。
所以這個指南重點在創建 Android Libraries. - 給你的 Library 命名并選擇一個最小的 SDK 版本,然后點擊 Finish。
一旦 Gradle 項目同步完成,庫模塊將出現在左邊的 Project 面板中。如果你沒看到新模塊文件夾,請確保 Android view 已顯示.
將 應用模塊 轉換成 庫模塊
如果你有想重用代碼的應用模塊,可以把它轉換成一個庫模塊,如下所述:
- 打開現有應用模塊的 build.gradle 文件,在頂部,你可以看到:
apply plugin:'com.android.application'
- 更改插件賦值為如下所示:
apply plugin:'com.android.library'
- 點擊 Sync Project with Gradle Files.
就這樣,這個模塊的整個結構保持不變,但它現在是作為一個 Android library 且構建將創建一個 AAR 文件而非 APK 文件.
添加你的 Library 作為依賴
在應用模塊中使用 Android Library 代碼,過程如下:
- 將 Library 添加到項目中有2種方法(如果創建的庫模塊在同一個項目中,可跳過這步)
-
添加已編譯的AAR或JAR文件:
- 點擊 File > New Module
- 點擊 Import .JAR/.AAR Package,然后點擊 Next
- 輸入 AAR 或者 JAR 文件的位置,然后點擊 Finish
-
導入庫模塊到項目中:
- 點擊 File > New > Import Module
- 輸入庫模塊文件的位置,然后點擊 Finish
庫模塊已經復制到你的項目中,因此你能夠編輯 Library 代碼。如果你想保持 Library 代碼的唯一版本,那么這可能不是你想要的,你應該導入編譯好的 AAR 文件.
- 確保 Library 列在 settings.gradle 文件里,這里顯示為一個名字為 "my-library-module" 的 Library:
include ':app', ':my-library-module'
- 打開應用模塊的
build.gradle
文件,在dependencies
塊中添加如下代碼:
dependencies {
compile project(":my-library-module")
}
- 點擊 Sync Project with Gradle Files
在上面這個例子中,名為my-library-module
的 Android Library 模塊成為build.gradle
文件所在模塊的構建依賴.
現在可以在你的應用模塊中訪問任何 Android library 的代碼和資源,并且庫的 AAR 文件會在構建時打包到你的 APK。
然而,如果你想單獨分享你的 AAR 文件,你可以在project-name/module-name/build/outputs/aar/
找到它,也可以通過點擊 Build > Make Project 重新產生。
選擇資源公開
庫里的資源默認是公開的(public)。要讓所有資源為隱式私有(private),你必須定義至少一個具體的公開屬性(attribute as public)。資源包括你的項目res/
目錄中的所有文件,比如圖像。要阻止你的庫用戶訪問僅供內部使用的資源,你應該使用這種聲明一個以上公開資源的自動化私有指定機制。
公開資源需要添加聲明到你的庫的public.xml
文件。如果你之前沒有添加過公開資源,那你需要在你的庫的/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>
任何你希望對使用你的庫的開發者可見的資源都應該公開。例如,雖然 v7 appcompat library 的大部分資源都是私有的,但控制 Toolbar 組件以支持 material design 的屬性是公開的。
隱式地讓屬性私有不僅能阻止你的庫的用戶感知到內部庫資源(通過代碼完成推薦),還允許你去重命名或移除私有資源的同時不破壞庫的客戶(clients of library)。私有資源可以被代碼完成和 theme editor 篩選出來,Lint 會在你嘗試使用私有資源時警告你。
開發者需要考慮的內容
當你開發library module
和dependent apps
,你應該注意到下列行為和限制:
一旦你將library module
的引用添加到Android app module
,就可以設置它們的優先級(relative priority)。在構建時,所有庫根據優先級從低到高依次與應用合并.
- 資源合并沖突
構建工具合并庫模塊的資源到dependent app module
。如果給定的資源ID在這兩個模塊中都有定義,使用 app 的資源。
如果沖突發生在多個 AAR library 中,則使用從依賴列表中先列出的庫的資源。
為了避免相同ID資源的沖突,考慮用一個前綴或者其它一致性命名方案以在模塊(或所有項目)中保持唯一。
- 庫模塊可以包含 JAR library
你可以開發包含 JAR library 的庫模塊,但是,你需要手動編輯 dependent app module
的構建路徑,并添加 JAR 文件的路徑。
- 庫模塊可以依賴外部 JAR library
你可以開發依賴外部 JAR library 的庫模塊(比如 Maps
庫)。這種情況下,dependent app
必須建立對應包含外部庫的目標(比如 Google APIs Add-On)。 注意,庫模塊和 dependent app
必須在它們清單(manifest)文件的 <uses-library> 元素中中聲明外部庫。
- 庫模塊不能包括 raw assets
工具不支持在庫模塊中使用 raw asset
文件(保存在 assets/
目錄中)。app 使用的任意 asset 資源必須存儲在自身模塊的 assets/
目錄中.
- 應用模塊的
minSdkVersion
必須大于或等于其在庫中的定義
庫被編譯為 dependent app module
的一部分,所以庫模塊中使用的 APIs 必須與app module
支持的平臺版本兼容。
- 每個庫模塊都創建它自己的R類
當你建立有依賴的應用模塊,庫模塊被編譯到 AAR 文件然后被添加到應用模塊。因此,每個庫都有根據自身包名命名的R類。由主模塊與庫模塊生成的R類被創建于被需要的所有模塊的包,
- 庫模塊可以包含自己的 ProGuard 配置文件
你可以對庫啟用代碼壓縮,通過添加一個包含 ProGuard 指令的 ProGuard 配置文件到你的庫中。構建工具將這個文件嵌入庫模塊生成的 AAR 文件中。當你添加庫到一個應用模塊,庫的 ProGuard 文件將被追加到應用模塊的 ProGuard 配置文件中(proguard.txt)。
將 ProGuard 文件嵌入庫模塊,使你能確保依賴你的庫的應用模塊就不需要手動更新它們的 ProGuard 文件就能使用你的庫。當 Android 應用模塊運行 ProGuard 時,它會同時使用應用模塊與庫模塊的指令所以你不需要單獨對庫運行 ProGuard。
在你的庫的 build.gradle
文件的 defaultConfig
塊內使用 consumerProguardFiles
方法指定配置文件名稱。例如,以下代碼片段設置 lib-proguard-rules.txt
為庫的 ProGuard 配置文件:
android {
defaultConfig {
consumerProguardFiles 'lib-proguard-rules.txt'
}
...
}
默認情況下,應用模塊引用庫使用 release
構建,即使應用模塊使用 debug
構建類型。要對庫使用不同的構建類型,你必須添加依賴到應用模塊 build.gradle
文件的 dependencies
塊同時在庫模塊的 build.gradle
文件中設置 publishNonDefault
為 true
。例如,下列代碼段置于應用的 build.gradle
文件中使得應用在 debug
模式構建時庫使用 debug
構建類型,應用在 release
模式構建時庫使用 release
構建類型:
dependencies {
debugCompile project(path: ':library', configuration: 'debug')
releaseCompile project(path: ':library', configuration: 'release')
}
你還須要在庫的 build.gradle
文件添加下列代碼,對使用它的項目暴露庫的 non-release
配置:
android {
...
publishNonDefault true
}
注意:publishNonDefault 會增加構建時間。
要確保你的庫的 ProGuard 規則不對應用模塊產生多余的壓縮副作用,包含的規則需要禁用對你的庫無用的 ProGuard 特性。這些規則幫助開發者處理與應用模塊中現存代碼的沖突。舉個例子,你的庫的 ProGuard 文件可以在應用模塊壓縮指定什么代碼需要被保留。
注意: Jack toolchain 僅支持 ProGuard 的壓縮(shrinking)和混淆(obfuscation)選項。