资讯专栏INFORMATION COLUMN

Android 开发使用 Gradle 配置构建库模块的工作方式

plus2047 / 2572人阅读

摘要:开发过程中,我们不可避免地需要引入其他人的工作成果。库模块导入方式显然无法完成任务,因为其是通过拷贝方式导入。另外,考虑到构建问题,库模块使用的插件与应用模块尽量保持一致。

Android 开发过程中,我们不可避免地需要引入其他人的工作成果。减少重复“造轮子”的时间,投入到更有意义的核心任务当中。

Android 库模块在结构上与 Android 应用模块相同。提供构建应用所需的一切内容,包括源代码(src)、资源文件(res)和 Android 清单文件(AndroidManifest.xml)。

Android Studio IDE 提供选项创建库模块:

在项目中创建一个新的库模块(New Module

将应用模块转换为库模块(因两者结构基本相同)

如果现有的应用模块包含希望重用的所有代码,可以通过修改 build.gradle文件:

// apply plugin: "com.android.application"
apply plugin: "com.android.library"

Android 库模块编译产物为 AAR,需要作为其他应用模块依赖项使用。

Android 应用模块编译产物为 APK,设备上可以直接运行。

Android AAR 类似 Java JAR,除了类文件还可以包含 Android 资源和一个清单配置文件(AndroidManifest.xml)。

导入本地外部模块

导入本地的外部模块(e.g. Project B b module)到当前主项目中(e.g. Project A)。
Project B b module 通常为库模块,我们需要在另一个 Project A 应用模块中使用它。

Android Studio IDE 提供选项以依赖项形式来添加库:

添加已编译的 AAR(或 JAR)文件(Import .JAR/.AAR Package

将库模块导入到您的项目中(Import Module

两者区别如下:

库模块导入方式,将会复制代码到其他项目:
Project A 目录下出现 Project B b module 的拷贝

库模块导入之后允许编辑库代码,但是修改只对当前项目生效:
Project A 目录下修改 b module 不会影响到 Project B b module

在现实开发过程中,我们希望维护一个统一版本的库模块,这样一来库模块的更新就会同步给所有依赖于它的项目:
Project A、Project C、Project D 都依赖于 Project B b module,库模块 b 的修改会同步到各个项目。

库模块导入方式显然无法完成任务,因为其是通过拷贝方式导入。

添加已编译的 AAR(或 JAR)文件可以完成任务,但是依然需要人工切换项目点选操作。


解决方案:
配置 gradle 通过本地相对路径指定库模块文件夹,实现本地外部模块导入。

打开主项目 settings.gradle 文件导入库:

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,默认使用应用模块的资源,e.g. @string/app_name

多个 AAR 库之间发生资源 ID 冲突,根据依赖项列表顺序,优先使用 dependencies 块顶部模块的资源

避免常用资源 ID 冲突的有效办法,是在各个模块中使用具有唯一性的前缀命名规范。

AndroidManifest 合并冲突

考虑到兼容性问题,应用模块的 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