Android 發佈自動版本號方案

之前看到一些自動化版本號打包的文章。若是您的項目是用 Git 管理的,而且恰巧又是使用 Gradle 編譯(應該絕大部分都是這樣的了吧?),本文試圖找到一種更加優雅的自動版本管理方法。 1 背景 咱們都知道,Android 應用的版本管理是依賴 AndroidManifest.xml 中的兩個屬性: android:versionCode:版本號,是一個大於 0 的整數,至關於 Build Number,隨着版本的更新,這個必須是遞增的。大的版本號,覆蓋更新小的版本號; android:versionName:版本名,是一個字符串,例如 "1.2.0",這個是給人看的版本名,系統並不關心這個值,可是合理的版本名,對後期的維護和 bug 修復也很是重要。 在使用了 Android Studio 或者 Gradle 編譯之後,咱們一般是在 build.gradle 裏面定義這兩個值,以下: android { ... defaultConfig { ... versionCode 1 versionName "1.0" } } 2 自動版本號 在這篇文章中 6 tips to speed up your Gradle build 發現了,可使用 Git 中 commit 的數量來做爲版本號(versionCode)。方案以下: def cmd = 'git rev-list HEAD --count' def gitVersion = cmd.execute().text.trim().toInteger() android { defaultConfig { versionCode gitVersion } } 這裏關鍵是這一行 git 命令 git rev-list HEAD --count,表示獲取當前分支的 commit 數量。 注:謝謝 @zhangls 提醒。原文直接使用了 6 tips to speed up your Gradle build 中的命令 git rev-list HEAD --first-parent --count,也就是帶了 --first-parent 選項。發現使用此選項並不合理,好比 這篇文章 中提到的,first-parent 可能會出現不穩定的狀況,這就可能致使得到的 commit 數量並不保證是遞增的。 這是一個絕妙的方案。由於在項目開發中,咱們的往 Git 庫中提交的 Commit 的數量應該是隻增不減的(固然,在極少的狀況下有例外),並且對應 Commit 的數量直接對應代碼當前的版本狀態,只要你作了代碼修改,版本號就應該增長。有些解決方案中,每次 Build 就會增長一次版本號,我的感受並不合適,若是是相同的代碼,發佈出去版本號應該保持一致,而不在於你編譯多少次。 另外,有些人可能會擔憂,每次版本發佈,可能會包含幾百個新的 commit,這樣的話 versionCode 會不會增加太快了,最後致使不夠用了。其實,徹底沒有必要擔憂,versionCode 是 int 類型,最大值是 2^31-1,也就是 21 億多,Android 源碼中,改動最活躍的 framework/base 全部分支到目前爲止也就 20 萬多個 commit,因此徹底夠用了。 3 自動版本名 前面經過一條簡單的命令實現了自動化的 versionCode,如今咱們看怎麼自動化versionName。 在正常的發佈流程中,在發佈新版本的時候,都會在版本庫中打 tag。通常狀況下,tag 名就是版本名,並且也建議這麼作,由於若是某個版本出現 bug,也能夠正好 checkout 這個 tag 來查看代碼。因此,如今的問題就是怎麼自動得到 git 庫中最新的最新 tag?原來,git 早就提供了命令 git describe,它的功能就是獲取從當期 commit 到距離它最近的 tag 的描述。默認都是 annoted tag,若是要指全部的類型的 tag 的話,就加 --tags參數。 此命令的詳細介紹在這裏:git-describe。舉例一個簡單的例子,假如你的當前代碼狀態以下: --A--B-...-C-->
     |     | v1.0  v1.1 執行 git describe 的結果是:v1.1,若是是以下的狀況: --A--B-...-C--D-->
     |     | v1.0  v1.1 執行 git describe 的結果是:v1.1-1-gXXXXXX,其中 1 表示當前代碼距離最近的 tag v1.1一個 commit,最新的 commit 的 id 是 XXXXXX。 可見,describe 命令很好的描述了當前的分支的版本狀態,咱們能夠直接使用這個它的輸出做爲版本號。在 build.gradle 中的使用以下: def cmd = 'git describe --tags' def version = cmd.execute().text.trim() android { defaultConfig { versionName version } } 這樣就能夠自動抽取 git 中的 tag 爲版本名了。有些同窗可能接受不了這樣版本名字 v1.1-1-gXXXXXX,這裏也能夠稍微作一些修改,使版本號更好看,以下: def pattern = "-(\\d+)-g" def matcher = version =~ pattern if (matcher) { version = version.substring(0, matcher.start()) + "." + matcher[0][1] } else { version = version + ".0" } 這樣的話,上面的版本名就變爲了 v1.0.0 和 v1.1.1 了。 4 優化 前面的那篇文章中說了,爲了儘量減小 gradle 腳本的運算,提升開發速度,咱們能夠把這樣的自動版本的計算放到 release 編譯中去。最後的寫法以下: def gitVersionCode() { def cmd = 'git rev-list HEAD --first-parent --count' cmd.execute().text.trim().toInteger() } def gitVersionTag() { def cmd = 'git describe --tags' def version = cmd.execute().text.trim() def pattern = "-(\\d+)-g" def matcher = version =~ pattern if (matcher) { version = version.substring(0, matcher.start()) + "." + matcher[0][1] } else { version = version + ".0" } return version } android { compileSdkVersion 23 buildToolsVersion "23.0.2" defaultConfig { applicationId "com.race604.example" minSdkVersion 15 targetSdkVersion 23 versionCode 1 versionName '1.0' } buildTypes { debug { // 爲了避免和 release 版本衝突
            applicationIdSuffix ".debug" } release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } applicationVariants.all { variant ->
        if (variant.buildType.name.equals('release')) { variant.mergedFlavor.versionCode = gitVersionCode() variant.mergedFlavor.versionName = gitVersionTag() } } } 至此,結合 git 和 gradle 咱們就實現了自動版本號。
相關文章
相關標籤/搜索