很多时候,在开发移动应用程序时,我们意识到我们必须一次又一次地解决同样的问题。此问题的解决方案是从库中提取解决方案,以便可以在其他项目中重新使用。
当我们在 Android 项目中这样做时,我们面临着一个选择:创建一个 Android 库或一个 Java/Kotlin 库。
如果我们的解决方案依赖于 Android 框架、图形资源或 AndroidX 库,那么我们将选择 Android。另一方面,如果我们不依赖于任何这些事情,我们可以为所有 JVM 创建一个库,以便在其他项目(如桌面应用程序甚至后端)上重新使用。
发布多模块 Android 库
但是,如果我们的解决方案可以在不依赖 Google 生态系统的情况下实现,但拥有它们将简化其在 Android 中的实现,我们该怎么办呢?
我们可以找到此问题的各种解决方案:
- 如果我们没有看到在 Android 之外使用的任何机会, 我们可以保留库的单个版本。
- 我们可以创建两个不同的库项目:一个用于 JVM,另一个用于 Android。不过,这将迫使我们复制大量代码。
- 我们可以有两个库项目,但这次,使Android库依赖于JVM一个。这样,库将只有促进其移动实现的代码,而不复制 Java/Kotlin 库上的内容。这种方法的问题在于,它将迫使我们为密切相关的代码创建两个不同的存储库:对 JVM 库的 API 的更改可能会影响 Android 的实现和 API。
- 具有单个多模块项目,并分别发布每个模块。这样,我们拥有最后一个选项的所有好处,现在我们还可以使用 AndroidStudio 的重构工具对 API 进行一些更改,而不会破坏任何库。
在这篇文章中,我们将重点介绍最后一点,发布多模块 Android库, 特别是如何设置 Gradle,以便我们可以以舒适的方式发布自己的模块,而无需复制发布的逻辑。
项目的模块结构如下:
- 示例: Android 应用程序, 显示如何使用和测试我们的库
- 核心:Kotlin/JVM 核心,以我们库为核心,具有所有可能的功能,无需依赖 Android 的框架
- Android: 科特林 / 安卓库与扩展或 API 仅在 Android 中可用
- 测试:测试 API,在库使用时促进测试编写
我们的目标是发布我们的许多模块:”com.group:mylibrary 模块:1.0.0″
因此,我们可以有一个一致的命名系统,所有已发布的库在存档’设置我们将在顶部添加此行:
x
根项目。名称="我的图书馆"
不同模块的设置是每个模块的通常设置。我们需要考虑到,当我们开发测试 API 时,JUnit 的依赖项从测试实施到实现,因为代码的实现可能需要断言,例如毕业生 ‘。
对于第一个配置,因此我们可以检查我们正在做的事情是否有效,首先我们将在计算机的本地 maven 存储库上发布库。为此,我们将将下一个插件添加到我们的渐变脚本中:
x
插件|
id"maven 发布"
Groovy
x
1
1
所有项目|
2
3
版本="1.0.0"
4
存储库|
5
谷歌()
6
jcenter()
7
}
8
}
现在,我们将在脚本中创建一个新块来设置模块的发布。由于我们不想发布整个项目,但每个模块,我们将使用"子项目"块1px;"•应用插件:"maven-发布"
这将应用我们添加到每个子模块中的项目的插件,而无需单独编辑其文件一个。
接下来,我们将添加基本设置:
Groovy
x
1
1
出版物]
3
马文(马文公开) |
4
artifactId="$rootProject.name - $project. name"
5
}
6
}
7
}
如果我们现在运行Gradle任务,'发布ToMavenLocal',我们将看到,在本地存储库(通常位于"$USER/.m2/存储库")4个新的目录已添加到com/Group/:mylibray-core,mylibrary-test,mylibrary-android,mylibrary-sample。
我们可以看到这里的第一个问题。我们不想发布我们的测试应用程序 - 它作为示例在存储库中或运行测试,并且不能发布。如果我们进入存储库,我们将看到两个额外的问题:jar 和 . aar 文件都包括在内。
要解决这些问题,我们必须修改发布块以考虑这些问题。
首先,让我们避免发布项目中包括的 Android 应用程序。这是因为"发布ToMavenLocal"任务会搜索定义发布块并发布它的所有模块。由于我们不想在所有模块中复制配置,因此必须阻止发布此特定模块。
为此,我们需要某种方法来标识模块。名称将是一个选项,因为我们知道模块的调用内容,但这将迫使我们更改配置一次/如果我们更改其名称或添加其他示例。
但是,由于我们真正想要做的是排除 Android 应用程序并离开库模块,我们将确定哪些模块是应用程序,为此,我们将定义"发布"块。要知道模块是否为应用程序,我们只需要检查它是否在其渐变脚本中应用com.android.应用程序插件:
Groovy
x
1
12
1
if (!插件。哈普卢金("机器人"))|
3
发布|
4
出版物|
5
马文(马文公开) |
6
artifactId="$rootProject.name - $project. name"
7
}
8
}
9
}
11
}
12
我们需要"评估后"块,因为我们希望插件已经应用于项目,以便我们检查它是否为应用程序。
如果我们删除以前生成的内容并再次发布,我们可以检查这次 mylibrary 样本如何未发布。
为了解决未生成的 .jar 文件以及 .pom 文件的依赖项问题,我们可以在出版物中添加"来自组件.java"行。
纯文本
x
1
1
[artifactid] = "$rootProject.name- $project. name"
3
从组件。贾瓦
4
}
但是,如果我们尝试同步 Gradle 文件,我们将看到它生成错误。出现此错误是因为并非所有模块都包含所需的 Java 组件。我们可以再次添加一个条件,并且仅在定义插件时使用组件:
纯文本
x
1
1
哈普卢金("java")|
2
从组件。贾瓦
3
}
如果我们现在同步和本地发布,我们将看到,mylibra-core 和 mylibrary-测试现在包括所有各自的.jar以及他们的.pom依赖项,但 mylibrary-android 仍然缺乏两者。
这里的问题是, mylibrary - android 是一个 Android 库, 而不是一个正常的 Jvm 库, 所以我们需要手动设置如何导出 .pom 依赖项, 如何生成 . aar 文件, 等等...值得庆幸的是,这是一个常见问题,并且有一个解决方案可用。
对于 Android 库的发布, 我们将使用 digital. wup 的插件: Android - maven - 发布插件。我们将将其添加到脚本中:
Groovy
x
1
1
id "maven 发布"
3
id"数字. wup. android - maven - 发布"版本"3.6.2"
4
}
然后,我们更改子模块和发布配置以使用它:
Groovy
x
1
21
1
应用插件:"maven-发布"
3
应用插件:"数字. wup. android - maven - 发布"
4
5
评估后|
6
如果(!插件。哈普卢金("机器人"))|
7
发布|
8
出版物|
9
[artifactid] = "$rootProject.name- $project. name"
11
if (插件.哈普卢金("java")|
12
从组件。贾瓦
13
否则如果(插件)。哈普卢金("机器人库"))|
14
从组件。机器人
15
}
16
}
18
}
19
}
20
}
21
}
再次,我们将添加一个条件,检查模块是否应用了"android库"插件,以便它可以使用组件.android。现在,最后,如果我们同步和发布,我们可以看到 mylibrary-android 包含 .aar 文件以及 .pom 依赖项。
现在,我们已经验证了发布是否正常工作,我们可以添加远程存储库。例如,我们可以添加快照存储库,以便我们的开发团队无需等待完整版本即可开始使用它,因此它们可以帮助我们在发布公共版本之前查找错误。为此,我们将在发布块下方的发布块中添加配置:
Groovy
x
1
10
1
马文]
3
名称"Nexussnapshot"
4
网址快照恢复
5
凭据|
6
用户名=部署用户名
7
密码=部署存储库密码
8
}
9
}
建议我们不要将用户或密码上载到存储库,而是将它们保存在 local.properties 文件中。现在,如果我们添加Gradle任务:
发布MavenPublicationToNexusSNAPSHOTrepository
我们的模块将作为分离的依赖项上载到存储库,用户将能够仅使用其项目中所需的部分。
文档,即生成它们的任务必须在子项目块内定义,并且其中一些工件可能与 java 插件或 android.library 有依赖关系。例如,这是我们如何使用源生成 .jar:
Groovy
x
1
12
1
哈普卢金("java")|
2
任务jvmSourcesJar(类型:Jar) |
3
存档分类器。设置("源")
4
从源集。主.所有来源
5
}
6
}
7
if (插件.哈普卢金("机器人库"))|
8
存档分类器。设置("源")
10
从机器人。源集。主.java.srcdirs
11
}
12
}
Comments are closed.