Android 使用maven publish插件发布产物(aar)流程实践
作者:Avengong 发布时间:2023-03-04 18:07:45
背景
平时开发中会把一些独立的功能模块抽取出来作为sdk,既方便业务接入,又能让其他业务线快速复用。那么我们就需要将sdk打包上传到maven仓库,让业务侧依赖即可。
一、编译后的产物
在上传产物到maven仓库之前,我们的知道产物到底是什么。
Android Gradle插件根据项目gradle中应用不同的插件类型在编译组装后会生成不同的产物:
1.1 APK 构件
Android项目的主工程app的gradle配置文件依赖:
apply plugin: 'com.android.application'
因此,在通过编译命令./gradlew assembleDebug
或./gradlew assembleRelease
后,就会在build/outputs/apk文件下生成产物:
如图,apk就是产物(构件)。
1.2 AAB(Android app bundle)构件
如果是海外市场,在Google Play上架的应用必须要打aab包,而不是之前的apk格式。具体区别就暂不讨论了~ 编译命令为:./gradlew bundleDebug
或./gradlew bundleRelease
。产物为:
1.3 AAR 构件
一般的module在编译打包后,会生成aar:
二、publish插件
有了产物,我们就需要把产物上传到maven仓库(一般是私有仓库),方便公司项目直接依赖。而上传就要用到publish插件。APG 3.6.0之前用的maven
插件,之后都用maven-publish
插件。
2.1 maven-publish插件使用
我们可以新建一个gradle文件,如:maven_publish.gradle。专门用来上传aar。配置如下:
//maven-publish 新方式
plugins {
//todo 1 上传插件
id 'maven-publish'
}
afterEvaluate{
publishing {
publications {
// Creates a Maven publication called "myPublication".
myPublication(MavenPublication) {
groupId 'com.sdk.aarpub'
artifactId 'aar-test'
version '1.2.2' // Your package version
// artifact publishArtifact //Example: *./target/myJavaClasses.jar*
artifact "build/outputs/aar/aar-test-release.aar"//aar包的目录
//带上依赖 ,否则会报错
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
def scopes = [configurations.compile]
if (configurations.hasProperty("api")) {
scopes.add(configurations.api)
}
if (configurations.hasProperty("implementation")) {
scopes.add(configurations.implementation)
}
if (configurations.hasProperty("debugImplementation")) {
scopes.add(configurations.debugImplementation)
}
if (configurations.hasProperty("releaseImplementation")) {
scopes.add(configurations.releaseImplementation)
}
// if (project.ext.targetType != "jar") {
// scopes.add(configurations.provided)
// }
scopes.each { scope ->
scope.allDependencies.each {
if (it instanceof ModuleDependency) {
boolean isTransitive = ((ModuleDependency) it).transitive
if (!isTransitive) {
println "<<<< not transitive dependency: [${it.group}, ${it.name}, ${it.version}]"
return
}
}
if (it.group == "${project.rootProject.name}.libs" || it.version == 'unspecified') {
return
}
if (it.group && it.name && it.version) {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
dependencyNode.appendNode('scope', scope.name)
}
}
}
}
}
}
// Repositories *to* which Gradle can publish artifacts
repositories {
maven {
//上传到项目本地仓库
url uri('../local_mavenrepo')
// credentials {
// username "default"
// password "default"
// }
}
}
}
}
在assemble命令后,执行publish命令:
./gradlew publish
2.2 maven插件使用
旧方式:
plugins {
//todo 1 上传插件
id 'maven'
}
uploadArchives{
// 方式一
repositories {
mavenDeployer{
repository(url: uri('../local_mavenrepo'))
//todo 2 配置版本信息 方式二
pom.groupId = 'com.sdk.aarpub'
pom.artifactId = 'aar-test'
pom.version = '1.1.0'
}
//mavenLocal 这个是本机上的maven本地缓存仓库
// mavenLocal()
}
}
在assemble命令后,执行uploadArchives命令:
./gradlew uploadArchives
2.3 业务侧使用
在项目的根gradle文件中,配置仓库:
maven { url '../local_mavenrepo/'}
在对应的模块中引入依赖:
implementation 'com.sdk.aarpub:aar-test:1.2.2'
三、问题总结
3.1 报错
项目中依赖本地aar的时候打包报错Direct local .aar file dependencies are not supported when building an AAR.....
原因:当打包aar时候直接依赖本地的aar是不被允许的。 解决方案:通过把依赖的aar放到单独的模块中,让直接依赖本地aar变成依赖模块。
新建一个文件夹aar-lib
新建一个libs文件夹,把
oaid_sdk_1.0.30.aar
放入到libs目录中
新建build.gradle文件,写入如下内容:
configurations.maybeCreate("default")
def publishArtifact = artifacts.add("default", file('libs/oaid_sdk_1.0.30.aar'))
在项目的settings文件中引入该模块:
include ':aar-lib'
删除报错模块中的aar文件,替换原来依赖方式:
// implementation files('libs/oaid_sdk_1.0.30.aar') 旧的方式
implementation project(path:":aar-lib")
3.2 module打包aar时依赖aar导致的类引用不到的问题
3.1 只是解决了在项目打包过程中依赖本地aar的问题。 当module作为sdk同时又依赖aar时,此时接入sdk会报错,提示引用不到aar中的类。当然我们可以直接把aar给到业务测,直接引入即可,但这样增加了接入成本。因此,我们的解决方案跟原理跟3.1一样,但是会把aar上传到远程库,作为远程来依赖。
比如 A模块依赖了oaid_sdk_1.0.30.aar,同时A模块作为sdk是要提供给业务侧app使用的。
按照3.1的方式创建一个aar-lib,build.gradle内容有所不同:
plugins {
id 'maven-publish'
}
//生成文档注释
task androidJavadocs(type: Javadoc) {
failOnError = false
source = android.sourceSets.main.java.srcDirs
ext.androidJar = "${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar"
classpath += files(ext.androidJar)
}
//将文档打包成jar
task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
archiveClassifier.set('javadoc')
from androidJavadocs.destinationDir
}
//将源码打包,这一点对kotlin来说很重要,否则业务侧无法看到源码
task androidSourcesJar(type: Jar) {
archiveClassifier.set('sources')
from android.sourceSets.main.java.srcDirs
}
configurations.maybeCreate("default")
def publishArtifact = artifacts.add("default", file('libs/oaid_sdk_1.0.30.aar'))
afterEvaluate{
publishing {
publications {
myPublication(MavenPublication) {
groupId 'com.sdk.aarpub'
artifactId 'aar-lib'
version '1.0.0' // Your package version
artifact(androidSourcesJar)//将源码打包进aar,如果不需要可以去掉
artifact(androidJavadocsJar)//将注释打包进aar,如果不需要可以去掉
// 将aar推送到远程仓库
artifact publishArtifact //Example: *./target/myJavaClasses.jar*
}
}
// Repositories *to* which Gradle can publish artifacts
repositories {
maven {
url uri('../local_maverepo')
// credentials {
// username "default"
// password "default"
// }
}
}
}
}
执行发布命令:
./gradlew :aar-lib:publish
让A模块依赖第二步中推送到远程的aar库:
implementation 'com.sdk.aarpub:aar-lib:1.0.0'
重新打包A模块,当app依赖A模块时候,A模块中的aar就会被引用到了 当然在A模块发布的时候记得要带上依赖:
//带上依赖 ,否则会报错
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
def scopes = [configurations.compile]
if (configurations.hasProperty("api")) {
scopes.add(configurations.api)
}
if (configurations.hasProperty("implementation")) {
scopes.add(configurations.implementation)
}
if (configurations.hasProperty("debugImplementation")) {
scopes.add(configurations.debugImplementation)
}
if (configurations.hasProperty("releaseImplementation")) {
scopes.add(configurations.releaseImplementation)
}
// if (project.ext.targetType != "jar") {
// scopes.add(configurations.provided)
// }
scopes.each { scope ->
scope.allDependencies.each {
if (it instanceof ModuleDependency) {
boolean isTransitive = ((ModuleDependency) it).transitive
if (!isTransitive) {
println "<<<< not transitive dependency: [${it.group}, ${it.name}, ${it.version}]"
return
}
}
if (it.group == "${project.rootProject.name}.libs" || it.version == 'unspecified') {
return
}
if (it.group && it.name && it.version) {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
dependencyNode.appendNode('scope', scope.name)
}
}
}
}
来源:https://juejin.cn/post/7064160157604773925


猜你喜欢
- /// <summary> /// 读写INI文件的类。
- 一般认为:foreach (object obj in checkedListBox1.SelectedItems)即可遍历选中的值。其实这
- 目录wait-notifyjoin方式ReentrantLockReentrantLock+ConditionSemaphore三个线程T1
- 最近,项目上涉及到了图像压缩,发现原有的图像压缩功能,虽然保证了图像的大小300K以内,但是压缩后的图像看的不在清晰,并且,限定了图片的He
- Spring的事务隔离级别和事务的传播行为是面试中经常考察的问题,做个简单的总结。传播行为在SpringBoot中通过Transaction
- 一,“==”与equals()运行以下代码,如何解释其输出结果?public class StringPool { public
- 什么是反射机制反射是java语言的一个特性,它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作。例如它允许一个ja
- 本文实例为大家分享了ManualResetEvent的使用方法,供大家参考,具体内容如下1. 源码下载:下载地址:ManualResetEv
- 本文为大家分享了SpringBoot使用邮箱发送验证码实现注册功能实例,供大家参考,具体内容如下这里有两种方式:使用Apache Commo
- 在进行java编程的时候,我们可以生成可运行的jar文件,但是鉴于平台的不同,我们可能需要将jar文件转化为exe格式。今天,小编就用一款叫
- 在Java编程过程中,我们常常会遇到比较基本类型或者对象之间的大小关系,下面我们来看看怎么去比较。源码如下:package object;c
- 需要装一个插件:File - Settings- Plugins - 搜索gson 安装GsonFromat;如下两张图安装完成后 ,新建一
- 关于在Android中实现ListView的弹性效果,有很多不同的方法,网上一搜,也有很多,下面贴出在项目中经常用到的两种实现ListVie
- 最近一直在使用邮件发送功能,老是遇到问题,后面才找到,原来并不是程序问题引起的,我吧问题整出来, javax.mail.SendFailed
- 在项目推进中,如果说第一件事是搭Spring框架的话,那么第二件事情就是在Sring基础上搭建日志框架,我想很多人都知道日志对于一个项目的重
- 基本要点1、Lombok作用:在我们的实体类中,我们再也不需要声明get、set、有参无参等方法,统统可以通过Lombok注解来实现同样的功
- 一.继承的类型在面向对象的编程中,有两种截然不同继承类型:实现继承和接口继承1.实现继承和接口继承*实现继承:表示一个类型派生于基类型,它拥
- 前言之所以会有这篇文章,是因为公司的开发环境比较老,寻找一些jar包的时候总是会纠结对应的编译版本,感觉很麻烦,所以写了一个工具类用于读取c
- 可变数目参数的好处就是在某些情况下可以方便地对参数个数不确定情况的实现,例如计算任意数字的加权和,链接任意字符串为一个字符串等。看下例子:p
- 前言:1.最近项目上在测试人员压测过程中发现了OOM问题,项目使用springboot搭建项目工程,通过查看日志中包含信息:unable t