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