Android组件化开发是一个非常好的方式,特别是当android项目越做越大时,组件化开发可以提高代码的可维护性和可扩展性,而一般组件化方式是将一个android项目拆分成多个子module,如下即为我们一个IM项目的module依赖关系:

1
2
3
4
5
6
├──demo Module #项目主module
├──imKit #IM UI module
| ├──imMap #IM 地图 module
| └──imLib #IM 底层库 module
└──imPush #IM 推送 module
└──imLib #IM 底层库 module

配置提交的服务器信息

在使用gradle提交module到maven服务器之前,可以在工程的gradle.properties文件中,配置好全局的相关的maven服务器信息变量,以便项目中各个module的build.gradle文件方便使用,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#版本号
VERSION_NAME=1.1.0
#如果使用以 -SNAPSHOT结尾的version,将自动提交到snapshot对应的repository url中
#VERSION_NAME=1.1.0-SNAPSHOT
#提交的module所属group
GROUP=com.yxt.sdk.library_im
#配置提交的每个子module对一个的artifact id
KIT_POM_ARTIFACT_ID=imkit
MAP_POM_ARTIFACT_ID=immap
PUSH_POM_ARTIFACT_ID=impush
LIB_POM_ARTIFACT_ID=imlib
#配置打包模式
POM_PACKAGING=aar
#本文作者在本地环境使用nexus软件搭载本地maven服务器,因此需要配置nexus账号,方便提交时需要使用
NEXUS_USERNAME=deployment
NEXUS_PASSWORD=123456
#release/snapshot 对应的repository地址
RELEASE_REPOSITORY_URL=http://localhost:8081/repository/maven-releases/
SNAPSHOT_REPOSITORY_URL=http://localhost:8081/repository/maven-snapshots/

独立module的gradle maven 提交

每一个module都将作为一个library提交到maven服务器中,其中imLib作为最底层module(即作为不依赖于项目中其他module的单独module)的配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#代码位于imLib module的build.gradle
#添加两个plugin
apply plugin: 'maven'
apply plugin: 'signing'
#添加是否ReleaseBuild的判断
def isReleaseBuild() {
return VERSION_NAME.contains("SNAPSHOT") == false
}
#添加uploadArchives task
afterEvaluate { project ->
uploadArchives {
repositories {
mavenDeployer {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
#配置pom信息
pom.groupId = GROUP
pom.artifactId = LIB_POM_ARTIFACT_ID
pom.version = VERSION_NAME
#配置提交到maven服务器的目标repository地址,以及提交所需提供的账号密码
repository(url: RELEASE_REPOSITORY_URL) {
authentication(userName: NEXUS_USERNAME, password: NEXUS_PASSWORD)
}
snapshotRepository(url: SNAPSHOT_REPOSITORY_URL) {
authentication(userName: NEXUS_USERNAME, password: NEXUS_PASSWORD)
}
}
}
}
signing {
required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
sign configurations.archives
}
}

当做好如上配置时,会在对应module的gradle控制边栏中多出一个uploadArchives的选项,如下图所示,双击即可对imLib提交

uploadArchives示意图

gradle提交说明

在上述过程中,gradle提交实际上对imLib module进行编辑打包生成aar文件之后,进行提交。

提交aar文件的同时,还会生成pom文件,一同提交。对于pom文件,简单的来说,改文件指明了提交的aar文件所需要依赖的其他maven组件,而依赖的项目有哪些,则是在提交过程中gradle根据build.gradle中的dependence模块进行生成,如下图所示

pom示意图

非独立module的gradle maven 提交

上一小节提到,gradle提交maven服务器时会根据module的build.gradle中dependence部分进行生成pom文件中的依赖配置,对于imLib这种独立的module一般情况下不会有任何问题,但是对于imKit这种依赖于项目中子module(imLib)的非独立module,gradle则不能正确生成pom文件,如下图所示:

pom_error示意图

很明显,gradle无法找到imKit module依赖imLib module的版本号,因此在生成pom时,填入了“unspecified”, 此时其他项目如果通过gradle引用imKit组件,则会发生编译错误

为了解决这个问题需要对imKit这类非独立的module在gradle提交时做特殊处理,其中一种处理办法是,提交过程中动态修改POM配置,使其指向正确的版本。对于imkit module的build.gradle的maven提交部分添加一下控制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#添加uploadArchives task
afterEvaluate { project ->
uploadArchives {
repositories {
mavenDeployer {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
#配置pom信息
pom.groupId = GROUP
pom.artifactId = LIB_POM_ARTIFACT_ID
pom.version = VERSION_NAME
#配置提交到maven服务器的目标repository地址,以及提交所需提供的账号密码
repository(url: RELEASE_REPOSITORY_URL) {
authentication(userName: NEXUS_USERNAME, password: NEXUS_PASSWORD)
}
snapshotRepository(url: SNAPSHOT_REPOSITORY_URL) {
authentication(userName: NEXUS_USERNAME, password: NEXUS_PASSWORD)
}
#控制pom配置,使"unspecified"指向正确版本号
pom.whenConfigured { pom ->
pom.dependencies.forEach { dep ->
if (dep.getVersion() == "unspecified") {
dep.setGroupId(GROUP)
dep.setVersion(VERSION_NAME)
}
}
}</span>
}
}
}
signing {
required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
sign configurations.archives
}
}