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