优雅的解决使用fatAar打包.aar时遇到的依赖问题

2,579 阅读2分钟

前言:我们在开发sdk时,经常会需要将产物aar上传到maven库中,而sdk又需要依赖一些公共模块或者第三方库,这个时候简单的使用implementation就会出现问题,一是无法将依赖的公共模块打包进sdk中,二是将依赖的第三方库比如gson打包进aar后,别人依赖时又会出现版本冲突(duplicated class),如果不将第三方库打进aar,别人依赖时又必须单独引入,很是麻烦。本文介绍了一种比较优雅的方式,解决了这样的问题。

直接上最终解决方案:

  1. 在项目的build.gradle中添加fataar依赖,注意要加到文件的最上方,否则会导致编译不过:
repositories {
    dependencies {
        classpath 'com.github.kezong:fat-aar:1.3.6'
    }
}
  1. 在lib的module模块的build.gradle中这样添加依赖:
plugins {
    id 'com.android.library'
}
apply plugin: 'com.kezong.fat-aar'
apply from: 'upload.gradle'

....
....

dependencies {
    implementation "com.squareup.okhttp3:okhttp:$okhttpVersion"
    api "com.google.code.gson:gson:$gsonVersion"
    
    if(isSdkMode.toBoolean()){
        embed project(":base")
    } else {
        api project(":base")
    }
}

使用embed替换之前的implementation或者api就可以将base模块打包进aar中了。

  1. upload.gradle是用来将lib库打包上传的maven的工具,主要解决办法也是在这个文件里实现的。先上代码:
apply plugin: 'maven-publish'

def USERNAME = "xiaoqiang"
def PASSWORD = "xiaoqiang"
def REPOSITORY_URL = "https://xiaoqiang.com/test-snapshot/"

publishing {
    publications {
        Production(MavenPublication) {
            groupId = "com.example.xiaoqiang"
            artifactId = "xiaoqiang"
            version = "$sdkVersion"
            afterEvaluate { artifact(tasks.getByName("bundleReleaseAar")) }
            pom.withXml {
                def dependencies = asNode().appendNode('dependencies')
                def dependency = dependencies
                        .appendNode("dependency")
                dependency.appendNode("groupId", "com.squareup.okhttp3")
                dependency.appendNode("artifactId", "okhttp")
                dependency.appendNode("version", "$okhttpVersion")
      
                dependency = dependencies
                        .appendNode("dependency")
                dependency.appendNode("groupId", "com.google.code.gson")
                dependency.appendNode("artifactId", "gson")
                dependency.appendNode("version", "$gsonVersion")
            }
        }
    }

    repositories {
        maven {
            url REPOSITORY_URL
            credentials {
                username = USERNAME
                password = PASSWORD
            }
            allowInsecureProtocol true
        }
    }
}

这里需要注意的是:snapshot版本的版本名字必须带snapshot,否则会上传失败。这样做的原理其实就是将第三方依赖写进aar的pom文件中,别人以maven形式远程依赖我们的sdk时,gradle会自动拉下来pom文件中的依赖版本。另外,如果外部也依赖了gson的话,版本不一致也不会出现冲突,外部引用用的是外部的版本,sdk用的是pom文件中的版本。

  1. 一般情况下,app模块会作为demo调试用,这个时候在app的build.gradle中可以这样配置:
dependencies {
    //引用 sdk
    if (sdkMode.toBoolean()) {
        implementation("com.example.xiaoqiang:xiaoqiang:$sdkVersion")
    } else {
        implementation project(":sdk")
    }
}

当然,在添加依赖时,也要在setting.gradle中声明库地址,包括aar发布的地址以及依赖的第三方库的地址:

repositories {
    google()
    mavenCentral()
    maven {
        allowInsecureProtocol true
        url 'http://****.*****.com/repository/maven-public/'
    }
    maven {
        url 'https://maven.aliyun.com/repository/public/'
    }
}

其中sdk的版本号及第三方依赖的版本我都抽离出来放在gradle.properties文件中了,因为这里可以定义一些全局变量,这样在每次发布aar时只需要在这一个文件里修改变量的值就可以啦。

sdkMode=true
sdkVersion=0.0.1-SNAPSHOT
gsonVersion=2.10
okhttpVersion=4.10.0

到此已经全部配置完成。改一下sdkVersion的值,在gradle点一下publish就可以将sdk上传到maven库了,然后在sync一下,就可以把刚刚上传的sdk拉下来验证了。注意:sdkMode的值在publish时必须是true。 本地调试时,只需要将sdkMode改为false就可以自动依赖本地模块了。