引言
在单一项目中,特别是模块化的开发模式下,我们通常会抽出一些全局共用的逻辑,放在一个 base-xxx 之类的模块里,在其他模块中,通过
implementation project(path: ':base-xxx')
的方式进行模块依赖。
但开头也有提到,这种形式多用于单项目内部。如果需要跨项目使用同一个模块,就不太合适了。虽然借助svn、git等版本控制工具也可以同步代码,但需要对文件夹单独进行版本管理,即外部文件夹属于一个git项目,内部文件夹属于另一个git项目,这种复杂的目录关系和文件管理会造成很强的歧义,而且引入了很多不必要的管理工作。
对于这种公用模块,更好的管理办法是将其当作一个单独的项目来维护。使用方就不再关心起具体的实现,只需要对其输出物进行依赖即可。
简单来看的话,可以把输出的aar或jar包直接拿来用,但使用aar包有一个显著的缺陷:依赖传递丢失。
gradle脚本的依赖项里,使用 implementation 和 api 声明的依赖作用域不同,其中 api 可以对外暴露自身依赖,使用方也同步获得对应依赖。但打包成aar或jar后,这部分信息就丢失了。
而在Maven机制中,对依赖的管理是依靠pom文件实现的,dependencies中添加的依赖项会同时下载对应的包和pom文件,本文我们就一起来看看怎么通过gradle脚本上传自己的库,完成gradle依赖的支持。
参考文档:https://docs.gradle.org/current/userguide/publishing_setup.html
上传者举例
gradle工具对maven的支持可以说很完善了,在模块的gradle脚本文件中引用与简单配置即可。下面贴出完整的子项目脚本,以及对应说明:
apply plugin: 'com.android.library'
apply plugin: 'maven'
android {
compileSdkVersion 30
defaultConfig {
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
api 'com.squareup.okhttp3:okhttp:4.7.2'
api 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.7.2'
}
// ------------- 以下为上传相关配置 -------------
task androidSourcesJar(type: Jar) {
archiveClassifier.set('sources')
from android.sourceSets.main.java.sourceFiles
}
artifacts {
archives androidSourcesJar
}
mavenDeploy {
repositories {
mavenDeployer {
repository(url: https://nexus.simple.net/repository/android-releases/) {
authentication(userName: xxxxxx, password: xxxxxx)
}
pom.project {
groupId com.simple
artifactId base-xxx
version 1.3.25
packaging 'aar'
}
}
}
}
关键部分说明:
apply plugin: 'maven' 引入maven脚本支持,可以使用其中的方法和能力
mavenDeploy 定义一个闭包,名字随意,这个就是我们要直接执行的命令
repository 指定maven仓库地址和对应用户信息;可以是mavenCentral,可以是自建的nexus,也可以是本地文件夹路径uri。
groupId 所属组,推荐直接使用包名
artifactId 名称,不解释
version 发布的版本,注意与android.defaultConfig中的versionCode、versionName区分,与这两者完全无关,maven中只认这个版本名。
artifacts (非必要)用于声明组件,其中指定对应task:androidSourcesJar,会在打包时执行,将 源码 也打包发布。
aar和jar包中的是编译过后的class文件,注释信息都丢失了,很多变量名和参数名也会变成var1、var2这种,如果是内部使用,建议同时打包源码,方便开发人员阅读与调试。
本地模拟仓库环境
在私库环境不具备时,可以使用本地文件夹暂时代替,用于验证编译过程。对maven来说,只需要指定一个url,能往其中写入文件与下载对应文件即可,我们将一个本地路径转成uri即可使用:
apply plugin: 'com.android.library'
apply plugin: 'maven'
android {
......
}
dependencies {
......
}
mavenDeploy {
repositories {
mavenDeployer {
repository(url: uri("/Users/wwf/Desktop/env/localRepo"))
pom.project {
groupId com.simple
artifactId base-xxx
version 1.3.25
}
}
}
}
抛开源码,简化过后就可以得到上面的脚本了,其实 **** 也可以不配置,会根据项目名和模块名生成对应的 groupId 和 artifactId,版本号为unspecified,但还是建议明确声明。
执行gradle命令:gradle mavenDeploy
,注意执行目录。
成功后即可在对应文件夹中发现如下文件:
使用者举例
与我们日常开发相同,需要在项目根脚本中指定要查找依赖的目标仓库。以mavenCentral为例:
---------- build.gradle in root projec ----------
buildscript {
repositories {
// 等效于mavenCentral()
maven { url "https://repo1.maven.org/maven2/" }
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.0'
......
......
}
}
allprojects {
repositories {
// 等效于mavenCentral()
maven { url "https://repo1.maven.org/maven2/" }
}
}
其中 allprojects 下的 repositories 中声明的是子项目查找的仓库。如果书接上文,使用本地仓库,就需要配置一个本地路径url,使用maven储存协议:
buildscript {
......
}
allprojects {
repositories {
// 等效于mavenCentral()
maven { url "https://repo1.maven.org/maven2/" }
maven { url: uri("/Users/wwf/Desktop/env/localRepo") }
}
}
配置好后就可以像使用远程仓库中其他依赖一样,使用本地仓库中的包啦!
全文完,如有不足请多指教,共同进步。