Android SDK 開發(fā)—發(fā)布使用踩坑之路
前言
在 Android 開發(fā)過程中,有些功能是通用的,或者是多個(gè)業(yè)務(wù)方都需要使用的。
為了統(tǒng)一功能邏輯及避免重復(fù)開發(fā),因此將該功能開發(fā)成一個(gè) SDK 是相當(dāng)有必要的。
背景
剛好最近自己遇到了類似需求,在開發(fā)完 SDK 之后,集成到項(xiàng)目或者提供給別人的時(shí)候遇到了一些坑,這里分享一下,以避免其他需要開發(fā) SDK 的開發(fā)者們重復(fù)踩坑。
文章要說明的內(nèi)容如下:
- 集成方式對(duì)比
- AAR 集成方式的一些坑
- 使用 maven publish 和 maven 將 SDK 推送到 maven 倉庫的區(qū)別
- Tips
- 總結(jié)
集成方式對(duì)比
SDK 開發(fā)完成之后,需要提供一種集成方式讓其他人可以使用。
集成方式這邊認(rèn)為大概有 3 種。
1. 提供 Module
這種集成方式把整個(gè) SDK 的源碼都提供給其他人。
- 優(yōu)點(diǎn):沒有什么坑,只要自己測(cè)試沒問題,別人一般可以直接使用。
- 缺點(diǎn):后續(xù)如果有更新,需要全量給別人進(jìn)行替換。
而且項(xiàng)目里面如果同時(shí)引用多個(gè)Module,項(xiàng)目結(jié)構(gòu)會(huì)增加很多代碼文件。
還有可能一不小心就更改了 SDK。
因?yàn)樵创a可以直接修改,沒有任何保護(hù)。
2. 提供 AAR 文件
這種集成方式是把 SDK 編譯之后提供 AAR 文件給其他人。
- 優(yōu)點(diǎn):只有一個(gè)文件,不需要給到具體源碼。
- 缺點(diǎn):某種情況下有坑,下面會(huì)講到。另外更新 SDK 不方便,每次更新需要用戶進(jìn)行 AAR 文件替換。
3. 推送到倉庫(這里以 MAVEN 倉庫為例)(推薦)
這種集成方式是把 SDK 編譯之后的 AAR 文件推送到倉庫,后續(xù)可以通過 implementation 或者 api(舊版本 Gradle 為 compile)引用。
- 優(yōu)點(diǎn):集成方便,跟第三方庫集成類似,方便開發(fā)者。而且有版本管理。
- 缺點(diǎn):maven publish 有個(gè)坑。見下文分析。
表格對(duì)比如下:
集成方式優(yōu)點(diǎn)缺點(diǎn)提供 Module沒有坑維護(hù)麻煩,沒有代碼保護(hù)提供 AAR 文件只有一個(gè)文件有坑,更新麻煩推送到倉庫集成方便,版本管理maven publish有個(gè)坑
AAR 集成方式的一些坑
一般 SDK 開發(fā)是封裝一些功能方便調(diào)用,因此比較少在 Module 里面引入第三方庫。這種情況下使用 AAR 集成是沒有太大問題的。
然而,當(dāng)你的 SDK 中引入第三方庫,比如 Retorfit 之類的庫時(shí)(不是直接引入 jar 包或者 aar 包),這個(gè)時(shí)候你使用 AAR 集成,運(yùn)行到對(duì)應(yīng)代碼時(shí)會(huì)提示 java.lang.NoClassDefFoundError 錯(cuò)誤。這個(gè)時(shí)候你
明明 Module 運(yùn)行沒問題,怎么 AAR 就報(bào)錯(cuò)了。
如果你嘗試在項(xiàng)目里面將 SDK 用到的第三方庫再引入一遍,就會(huì)發(fā)現(xiàn)程序沒報(bào)錯(cuò)了。
因此我們可以得出結(jié)論:
- AAR 不能傳遞第三方依賴
別慌,方法總比問題多。
我們可以通過將 SDK 推送到倉庫的方式來解決這個(gè)問題。
推送倉庫有很多,比如開源的 jcenter 之類的。
這邊考慮有些 SDK 是給公司內(nèi)部使用的,因此以 maven 為例進(jìn)行講解。
使用 maven publish 和 maven 將 SDK 推送到 maven 倉庫的區(qū)別
maven publish 其實(shí)是 maven 的一個(gè)升級(jí)。
所以一般優(yōu)先采用 maven publish。
這邊項(xiàng)目已經(jīng)使用了 maven publish 了,所以這邊一開始也是使用 maven publish。
結(jié)果坑來了。
發(fā)現(xiàn)出現(xiàn)和 AAR 一樣的錯(cuò)誤,依賴不能傳遞。
這,趕緊看一眼 pom 文件(跟 AAR 同級(jí)目錄),發(fā)現(xiàn)真的沒有依賴。
查了一下網(wǎng)上資料。發(fā)現(xiàn)
- https://discuss.gradle.org/t/using-the-maven-publish-plugin-no-dependencies-in-pom-xml/7599
有一個(gè)提問
當(dāng)然應(yīng)該有對(duì)應(yīng)的處理方式,但是由于項(xiàng)目時(shí)間需求比較緊,不想花太多時(shí)間,因此暫時(shí)沒有查找解決方式。
如果有朋友知道,可以留言,后續(xù)有空研究,有解決方法也會(huì)更新。
因此這里不展開討論 maven publish 的集成方式。
最后查閱資料使用了 maven 的推送方式。
那么如何使用呢?
1. 先使用本地倉庫,確保沒問題之后再使用遠(yuǎn)程的
在 Module 的 build.gradle 文件中添加如下代碼:
- apply plugin: 'maven' //指定使用 maven
- uploadArchives {
- repositories {
- mavenDeployer {
- pom.groupId = "com.maven.demo" //包名
- pom.artifactId = "login" //SDK 功能,自定義一個(gè)即可
- pom.version = "0.0.1" //版本號(hào)
- repository(url: "file://localhost/Users/用戶名/Library/Android/sdk/extras/android/m2repository/") //用戶名替換為自己的機(jī)器名,本地地址
- }
- }
- }
執(zhí)行 uploadArchives 任務(wù)就可以上報(bào)了。
然后到上面 url 指定的目錄或者通過瀏覽器打開可以看到上傳的相關(guān)文件。
查看 pom 文件可以看到依賴都在上面。
2. 使用遠(yuǎn)程倉庫,對(duì)上面略做修改。
- apply plugin: 'maven' //指定使用 maven
- uploadArchives {
- repositories {
- mavenDeployer {
- pom.groupId = "com.maven.demo" //包名
- pom.artifactId = "login" //SDK 功能,自定義一個(gè)即可
- pom.version = "0.0.1" //版本號(hào)
- repository(url: "網(wǎng)址") {
- authentication(userName: "用戶名", password: "密碼")
- }
- }
- }
- }
其中網(wǎng)址、用戶名和密碼記得分別替換。
別人需要使用時(shí)只需要在 Module 添加如下:
- implementation 'com.maven.demo.login.0.01'
所以倉庫的組成就是pom.groupId+pom.artifactId+pom.version
Tips:
1. SDK 開發(fā)可能遇到同一個(gè)版本比如 0.0.1 在發(fā)布之前經(jīng)常需要修改的情況。
這個(gè)時(shí)候如果你把修改后的 SDK 推送到遠(yuǎn)程,可能本地項(xiàng)目用的還是舊的內(nèi)容。
這種時(shí)候有兩個(gè)處理方式。
- 第一個(gè),更新版本號(hào),修改依賴新版本。
- 第二個(gè),執(zhí)行下面命令,強(qiáng)制從遠(yuǎn)程拉取,不使用緩存。
- ./gradlew build --refresh-dependencies
2. 使用遠(yuǎn)程倉庫時(shí),一般用戶名和密碼都不會(huì)直接推送到代碼倉庫,可能會(huì)放到構(gòu)建機(jī)。
這個(gè)時(shí)候需要使用類似于 local.properties 的外部文件來存放。
這個(gè)時(shí)候有個(gè)坑需要提醒一下,就是在 local.properties 定義比如maven_user_name=username,千萬記得不要加雙引號(hào),否則會(huì)出現(xiàn)認(rèn)證失敗,出現(xiàn)下面提示:
- Received status code 401 from server: Unauthorized
3. 使用 maven 的形式如何指定是 debug 還是 release?
通過在 android 塊里面添加
- android {
- defaultPublishConfig "release"
- }
可以指定。
通過查看 Module 的 build/outputs/aar 可以看到 aar 包。
通過查看 Module 的 build/poms/pom-default.xml 可以看到本地 pom 文件。
4. 有些開發(fā)者如果按照上面操作之后還是出現(xiàn) java.lang.NoClassDefFoundError 錯(cuò)誤,可以嘗試下面操作:
修改
- implementation 'com.maven.demo.login.0.01'
為
- implementation 'com.maven.demo.login.0.01' {
- transitive = true
- }
總結(jié)
- 1. SDK 開發(fā)完成之后發(fā)布給其他人使用最好放到遠(yuǎn)程倉庫(比如 maven)2. 如果出現(xiàn) SDK 引入的第三方庫沒有找到的錯(cuò)誤,記得到倉庫看下 pom 文件是否有對(duì)應(yīng)依賴