本人是一枚Android SDK开发程序猿,就是开发SDK以提供给客户使用。以前我们SDK开发本着能不依赖第三方就不依赖第三方的原则,使用的全是原生提供的API。由于上次经过爬虫 Android Push哪家强——分析豌豆荚1400个APP 得到使用OkHttp的APP占比已经很高了,再加上看到国外的SaaS服务公司提供的SDK对于接入第三方开源SDK很是开放。所以我们也想将底层网络库从传统的 HttpURLConnection
切换为 OkHttp3
。然而这才是噩梦的开始……
开发进行的很顺利,我们在自己的SDK module中添加了okhttp的依赖
dependencies { ... implementation 'com.squareup.okhttp3:okhttp:3.12.1' }
在测试demo APP中添加了SDK module依赖
dependencies { ... implementation project(':sdk-lib') }
嗯,demo APP运行的很完美,代码是跑的飞起。 但是当我们发布到Maven上去,然后新建一个APP直接添加我们的依赖的时候,出现问题了。
dependencies { ... implementation 'com.xxxx.xxxx:sdk-lib:1.0.0' }
居然报出 NoClassDefFoundError
什么情况?!我不是在我的sdk-lib已经添加了OkHttp的依赖了吗?!
java.lang.NoClassDefFoundError: Failed resolution of: Lokhttp3/MediaType;
根据官网 依赖项配置 的介绍
implementation 只是不对外暴露依赖的SDK的API而已呀,为什么主APP没有产生依赖呢?不是说运行时会提供?我们来看看最后Maven仓库中的pom文件
<?xml version="1.0" encoding="UTF-8"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <groupId>com.xxxx.xxxx</groupId> <artifactId>sdk-lib</artifactId> <version>1.0.0</version> <packaging>aar</packaging> <dependencies> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>3.12.1</version> <scope>runtime</scope> </dependency> </dependencies> </project>
我们看到scope的类型是runtime。百度后基本的做法就是在主APP的依赖中重新添加OkHttp的依赖,或者使用api替代implementation。好,那我们使用api依赖后再看看依赖的pom文件,发现scope的类型是compile。
<?xml version="1.0" encoding="UTF-8"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <groupId>com.xxxx.xxxx</groupId> <artifactId>sdk-lib</artifactId> <version>1.0.0</version> <packaging>aar</packaging> <dependencies> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>3.12.1</version> <scope>compile</scope> </dependency> </dependencies> </project>
重新新建一个APP并依赖新的sdk-lib,果然没问题,代码跑的飞起。
如果到这里基本已经结束了,那岂不是又是一篇水文?众所周知,我们在开发和发布的时候经常会有不同的依赖情况,比如开发的时候使用的是module依赖,发布的时候使用的线上Maven库依赖。比如需要发布的sdk-lib SDK依赖了一个自己开发core模块。
dependencies { ... debugApi project(':core-lib') releaseApi "com.xxxx.xxxx:core:$coreVersion" }
当我们使用gradle的 generatePomFileForReleasePublication
Task生成Pom文件发现,并没有core-lib的依赖,什么鬼?!不是说好用api就行了吗?!
<?xml version="1.0" encoding="UTF-8"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <groupId>com.xxxx.xxxx</groupId> <artifactId>sdk-lib</artifactId> <version>1.0.0</version> <packaging>aar</packaging> </project>
没办法,看来gradle的发布插件 maven-publish
已经满足不了我们了,那就自己编写pom依赖吧,把所有的 implementation 和 api 依赖都添加进去。如下,在APP的build.gradle中添加
publishing { publications { mavenAgent(MavenPublication) { artifact "${project.buildDir}/outputs/aar/${project.name}-release.aar" groupId yourGroupId artifactId yourArtifactId version yourVersion pom.withXml { writePom(asNode()) } } } } void writePom(node) { def allDependencies = new HashSet<DependencySet>() allDependencies.addAll(configurations.api.allDependencies) allDependencies.addAll(configurations.releaseApi.allDependencies) allDependencies.addAll(configurations.implementation.allDependencies) allDependencies.addAll(configurations.releaseImplementation.allDependencies) def iterator = allDependencies.iterator() while (iterator.hasNext()) { def dep = iterator.next() //移除project类型的依赖 if (dep.name == "unspecified" || dep.version == "unspecified") { iterator.remove() } } def depsNode = node.appendNode('dependencies') allDependencies.each { dep -> def depNode = depsNode.appendNode('dependency') depNode.appendNode('groupId', dep.group) depNode.appendNode('artifactId', dep.name) depNode.appendNode('version', dep.version) depNode.appendNode('scope', 'compile') } }
我们在gradle任务列表中执行下属两个任务(其中 mavenAgent
是你自己取的发布别名),并查看依赖情况。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <groupId>com.xxxx.xxxx</groupId> <artifactId>sdk-lib</artifactId> <version>1.0.0</version> <packaging>aar</packaging> <dependencies> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>3.12.1</version> <scope>compile</scope> </dependency> <dependency> <groupId>com.xxxx.xxxx</groupId> <artifactId>core</artifactId> <version>1.0.0</version> <scope>compile</scope> </dependency> </dependencies> </project>
好,大功告成,发布到线上jcenter仓库!让用户的代码跑的飞起!