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