Android SDK 開發——釋出使用踩坑之路

weixin_34377065發表於2018-12-07

前言

在 Android 開發過程中,有些功能是通用的,或者是多個業務方都需要使用的。

為了統一功能邏輯及避免重複開發,因此將該功能開發成一個 SDK 是相當有必要的。

背景

剛好最近自己遇到了類似需求,在開發完 SDK 之後,整合到專案或者提供給別人的時候遇到了一些坑,這裡分享一下,以避免其他需要開發 SDK 的開發者們重複踩坑。

文章要說明的內容如下:

  1. 整合方式對比
  2. AAR 整合方式的一些坑
  3. 使用 maven publish 和 maven 將 SDK 推送到 maven 倉庫的區別
  4. Tips
  5. 總結

整合方式對比

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 的推送方式。

那麼如何使用呢?

  1. 先使用本地倉庫,確保沒問題之後再使用遠端的
    在 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:

  1. SDK 開發可能遇到同一個版本比如 0.0.1 在釋出之前經常需要修改的情況。

這個時候如果你把修改後的 SDK 推送到遠端,可能本地專案用的還是舊的內容。

這種時候有兩個處理方式。

第一個,更新版本號,修改依賴新版本。

第二個,執行下面命令,強制從遠端拉取,不使用快取。

./gradlew build --refresh-dependencies
複製程式碼
  1. 使用遠端倉庫時,一般使用者名稱和密碼都不會直接推送到程式碼倉庫,可能會放到構建機。

這個時候需要使用類似於 local.properties 的外部檔案來存放。

這個時候有個坑需要提醒一下,就是在 local.properties 定義比如maven_user_name=username,千萬記得不要加雙引號,否則會出現認證失敗,出現下面提示:

Received status code 401 from server: Unauthorized
複製程式碼
  1. 使用 maven 的形式如何指定是 debug 還是 release?

通過在 android 塊裡面新增

android {
    defaultPublishConfig "release"
}
複製程式碼

可以指定。

通過檢視 Module 的 build/outputs/aar 可以看到 aar 包。

通過檢視 Module 的 build/poms/pom-default.xml 可以看到本地 pom 檔案。

  1. 有些開發者如果按照上面操作之後還是出現 java.lang.NoClassDefFoundError 錯誤,可以嘗試下面操作:

修改

implementation 'com.maven.demo:login:0.01' 
複製程式碼

implementation 'com.maven.demo:login:0.01' {
        transitive = true
}
複製程式碼

總結

  1. SDK 開發完成之後釋出給其他人使用最好放到遠端倉庫(比如 maven)
  2. 如果出現 SDK 引入的第三方庫沒有找到的錯誤,記得到倉庫看下 pom 檔案是否有對應依賴

關注公眾號一起交流:

相關文章