Android 開發過程當中,咱們不可避免地須要引入其餘人的工做成果。減小重複「造輪子」的時間,投入到更有意義的核心任務當中。
Android 庫模塊在結構上與 Android 應用模塊相同。提供構建應用所需的一切內容,包括源代碼(src
)、資源文件(res
)和 Android 清單文件(AndroidManifest.xml
)。java
Android Studio IDE 提供選項建立庫模塊:android
若是現有的應用模塊包含但願重用的全部代碼,能夠經過修改 build.gradle
文件:api
// apply plugin: 'com.android.application' apply plugin: 'com.android.library'
Android AAR 相似 Java JAR,除了類文件還能夠包含 Android 資源和一個清單配置文件(AndroidManifest.xml
)。app
導入本地的外部模塊(e.g. Project B b module)到當前主項目中(e.g. Project A)。
Project B b module 一般爲庫模塊,咱們須要在另外一個 Project A 應用模塊中使用它。ide
Android Studio IDE 提供選項以依賴項形式來添加庫:gradle
二者區別以下:ui
在現實開發過程當中,咱們但願維護一個統一版本的庫模塊,這樣一來庫模塊的更新就會同步給全部依賴於它的項目:
Project A、Project C、Project D 都依賴於 Project B b module,庫模塊 b 的修改會同步到各個項目。插件
解決方案:
配置 gradle 經過本地相對路徑指定庫模塊文件夾,實現本地外部模塊導入。日誌
打開主項目 settings.gradle
文件導入庫:code
include ':my-library-module' project(':my-library-module').projectDir = new File(settingsDir, '../my-library-module')
打開主項目應用模塊的 build.gradle
文件,並向 dependencies 塊中添加依賴:
dependencies { compile project(":my-library-module") }
將庫模塊引用添加至您的 Android 應用模塊後,庫模塊會根據優先級的順序與應用模塊進行合併。
避免經常使用資源 ID 衝突的有效辦法,是在各個模塊中使用具備惟一性的前綴命名規範。
考慮到兼容性問題,應用模塊的 minSdkVersion
必須大於或等於庫定義的版本。
庫模塊中如若使用到僅高版本 SDK 支持的 API,將會致使應用模塊編譯失敗。
Android 在切換到 Gradle 做爲構建系統以前,經過 Manifest 設置 minSdkVersion
,以後其值會被 build.gradle
文件中的值覆蓋。
Android 應用的 APK 文件中只能包含一個 AndroidManifest.xml
,不過 Android Studio 項目能夠包含多個該文件(來自主應用模塊及各個庫模塊)。所以,在構建應用時,Gradle 構建會將全部清單文件(AndroidManifest.xml
)合併。清單文件按照優先級從低到高合併,遵循特定規則合併各個清單文件中的全部 XML 元素 。
清單文件優先級由高到低的順序:
多個庫存在時,則其清單優先級與依賴順序即 dependencies 塊中的順序匹配。
Manifest merger failed 示例: android:theme
在多個 AndroidManifest.xml
被定義且值不一樣,形成合並衝突。
Project A 主項目 AndroidManifest.xml
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme">
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
Project B b Library Module AndroidManifest.xml
<application android:theme="Theme.AppCompat.Light.DarkActionBar">
遇到 Manifest 衝突參考 Gradle Console 給出的錯誤日誌和提示,解決衝突。
例如使用 tools:replace
方式避免屬性衝突,藉助 tools 域名空間(xmlns:tools="http://schemas.android.com/tools"
)設置 Manifest 的合併優先級。明確表示合併時移除低優先級 library module 中的相關屬性,使用高優先級 application module 中定義的對應屬性內容。
Project A 主項目 AndroidManifest.xml
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" tools:replace="android:theme">
考慮到多重嵌套依賴問題,Gradle 相似 Maven 支持傳遞依賴,即庫自己依賴於其餘庫,由此須要解決依賴之間的版本問題。
複雜的依賴關係極可能致使重複引入包,例如:support-v4
、support-v7
包,從而發生衝突。
多個模塊之間存在相同依賴而且發生衝突,能夠經過 exclude 語法過濾相同依賴:
// helloworld build.gradle ... compile ('com.example.helloworld:my-library-module:1.0.0') { exclude group: 'com.android.support', module: 'support-v4' exclude group: 'com.android.support', module: 'support-v7' }
上述方法是在主項目引入其餘庫模塊時進行過濾依賴,做爲庫模塊開發者咱們也應該考慮到其餘用戶的使用狀況。
provided 語法在建立 Android 庫模塊時很是有用,將依賴項添加到編譯過程當中,但不會添加到編譯輸出中。這樣一來減小最終 APK、AAR 產物大小,同時避免添加沒必要要依賴項。
注意:須要告知用戶此依賴項存在,由其如何決定引入依賴。
// my-library-module build.gradle ... ext.supportLibVersion = '26.1.0' dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) provided "com.android.support:appcompat-v7:${supportLibVersion}" }
Project A 依賴 a、b、c module,同時 a、b module 又依賴於 d module,且 a、b 各自依賴的 d module 版本(version)不一致,不一樣 version 的 d module 中 API 接口如若發生改變,Project A Build/Sync 將會失敗。 例如 version 1.0 中的方法 method1,在 version 2.0 被移除將會遇到 java.lang.NoSuchMethodError
。
建議儘量保持依賴項 d module version 一致,或者使用不一樣 version 可是差別不大,起碼作到 API 可以通用。
經過 ./gradlew dependencies
命令能夠查看依賴關係,附加參數能夠查看指定類型、模塊依賴關係:
./gradlew my-library-module:dependencies --configuration archives
archives - Configuration for archive artifacts. +--- com.android.support:recyclerview-v7:26.1.0 | +--- com.android.support:support-annotations:26.1.0 | +--- com.android.support:support-compat:26.1.0 | | +--- com.android.support:support-annotations:26.1.0 | | \--- android.arch.lifecycle:runtime:1.0.0 | | +--- android.arch.lifecycle:common:1.0.0 | | \--- android.arch.core:common:1.0.0 | \--- com.android.support:support-core-ui:26.1.0 | +--- com.android.support:support-annotations:26.1.0 | \--- com.android.support:support-compat:26.1.0 (*)
另外 Android 項目可使用 ./gradlew androidDependencies
。
另外,考慮到構建問題,庫模塊使用的 gradle 插件與應用模塊儘可能保持一致。
Android Gradle Plugin 版本不一致可能會影響到依賴項配置語法:
New configuration | Deprecated configuration |
---|---|
implementation | compile |
api | compile |
compileOnly | provided |
runtimeOnly | apk |