本人是一枚Android SDK開發程序猿,就是開發SDK以提供給客戶使用。之前咱們SDK開發本着能不依賴第三方就不依賴第三方的原則,使用的全是原生提供的API。因爲上次通過爬蟲 Android Push哪家強——分析豌豆莢1400個APP 獲得使用OkHttp的APP佔比已經很高了,再加上看到國外的SaaS服務公司提供的SDK對於接入第三方開源SDK非常開放。因此咱們也想將底層網絡庫從傳統的HttpURLConnection
切換爲OkHttp3
。然而這纔是噩夢的開始……php
開發進行的很順利,咱們在本身的SDK module中添加了okhttp的依賴java
dependencies {
...
implementation 'com.squareup.okhttp3:okhttp:3.12.1'
}
複製代碼
在測試demo APP中添加了SDK module依賴node
dependencies {
...
implementation project(':sdk-lib')
}
複製代碼
嗯,demo APP運行的很完美,代碼是跑的飛起。 可是當咱們發佈到Maven上去,而後新建一個APP直接添加咱們的依賴的時候,出現問題了。android
dependencies {
...
implementation 'com.xxxx.xxxx:sdk-lib:1.0.0'
}
複製代碼
竟然報出NoClassDefFoundError
什麼狀況?!我不是在個人sdk-lib已經添加了OkHttp的依賴了嗎?!apache
java.lang.NoClassDefFoundError: Failed resolution of: Lokhttp3/MediaType;
複製代碼
根據官網依賴項配置的介紹api
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。android-studio
<?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,果真沒問題,代碼跑的飛起。bash
若是到這裏基本已經結束了,那豈不是又是一篇水文?衆所周知,咱們在開發和發佈的時候常常會有不一樣的依賴狀況,好比開發的時候使用的是module依賴,發佈的時候使用的線上Maven庫依賴。好比須要發佈的sdk-lib SDK依賴了一個本身開發core模塊。網絡
dependencies {
...
debugApi project(':core-lib')
releaseApi "com.xxxx.xxxx:core:$coreVersion"
}
複製代碼
當咱們使用gradle的generatePomFileForReleasePublication
Task生成Pom文件發現,並無core-lib的依賴,什麼鬼?!不是說好用api就好了嗎?!app
<?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倉庫!讓用戶的代碼跑的飛起!