Android 发布自动版本号方案
以前看到一些自动化版本号打包的文章。如果您的项目是用 Git 管理的,并且恰巧又是使用 Gradle 编译(应该绝大部分都是这样的了吧?),本文试图找到一种更加优雅的自动版本管理方法。 背景
我们都知道,Android 应用的版本管理是依赖 AndroidManifest.xml 中的两个属性: android:versionCode:版本号,是一个大于 的整数,相当于 Build Number,随着版本的更新,这个必须是递增的。大的版本号,覆盖更新小的版本号;
android:versionName:版本名,是一个字符串,例如 "1.2.0",这个是给人看的版本名,系统并不关心这个值,但是合理的版本名,对后期的维护和 bug 修复也非常重要。
在使用了 Android Studio 或者 Gradle 编译以后,我们通常是在 build.gradle 里面定义这两个值,如下: android {
...
defaultConfig {
...
versionCode
versionName "1.0"
}
}
自动版本号
在这篇文章中 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 提醒。原文直接使用了 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 类型,最大值是 ^-,也就是 亿多,Android 源码中,改动最活跃的 framework/base 所有分支到目前为止也就 万多个 commit,所以完全够用了。 自动版本名
前面通过一条简单的命令实现了自动化的 versionCode,现在我们看怎么自动化versionName。 在正常的发布流程中,在发布新版本的时候,都会在版本库中打 tag。一般情况下,tag 名就是版本名,而且也建议这么做,因为如果某个版本出现 bug,也可以正好 checkout 这个 tag 来查看代码。所以,现在的问题就是怎么自动获得 git 库中最新的最新 tag?原来,git 早就提供了命令 git describe,它的功能就是获取从当期 commit 到距离它最近的 tag 的描述。默认都是 annoted tag,如果要指所有的类型的 tag 的话,就加 --tags参数。 此命令的详细介绍在这里:git-describe。举例一个简单的例子,假如你的当前代码状态如下: --A--B-...-C-->
| |
v1. v1.
执行 git describe 的结果是:v1.,如果是如下的情况: --A--B-...-C--D-->
| |
v1. v1.
执行 git describe 的结果是:v1.--gXXXXXX,其中 表示当前代码距离最近的 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.--gXXXXXX,这里也可以稍微做一些修改,使版本号更好看,如下: def pattern = "-(\\d+)-g"
def matcher = version =~ pattern if (matcher) {
version = version.substring(, matcher.start()) + "." + matcher[][]
} else {
version = version + ".0"
}
这样的话,上面的版本名就变为了 v1.0.0 和 v1.1.1 了。 优化
前面的那篇文章中说了,为了尽可能减少 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(, matcher.start()) + "." + matcher[][]
} else {
version = version + ".0"
} return version
} android {
compileSdkVersion
buildToolsVersion "23.0.2" defaultConfig {
applicationId "com.race604.example"
minSdkVersion
targetSdkVersion
versionCode
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 我们就实现了自动版本号。
Android 发布自动版本号方案的更多相关文章
- 最清晰的Android多屏幕适配方案
问题的引入 当您的Android应用即将发布的时候,如果你想让更多的用户去使用你的应用,摆在工程师面前的一个重要问题就是如何让你的应用能在各种各样的终端上运行,这里的各种各样首当其冲的就是不同的屏幕分 ...
- 一种让运行在CentOS下的.NET CORE的Web项目简单方便易部署的自动更新方案
一.项目运行环境 项目采用的是.NET5开发的Web系统,独立部署在省内异地多台CentOS服务器上,它们运行在甲方专网环境中(不接触互联网),甲方进行业务运作时(一段时间内)会要求异地服务器开机上线 ...
- Android实现自动更新功能
Android实现自动更新功能 Android自动更新的功能可以使用第三方的SDK来实现,但是类似友盟,就不支持x86手机的自动更新,科大讯飞,弹窗是全局的,小米手机就会默认把弹窗权限关掉不允许弹出提 ...
- 谷歌发布"自动机器学习"技术 AI可自我创造
谷歌发布"自动机器学习"技术 AI可自我创造 据Inverse报道,今年5月份,谷歌宣布其人工智能(AI)研究取得重大进展,似乎帮助科幻小说中最耸人听闻的末日预言成为现实.谷歌推出 ...
- 转: Android微信智能心跳方案
http://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=207243549&idx=1&sn=4ebe4beb8123f1b5 ...
- Android 双u盘方案【转】
本文转载自:https://blog.csdn.net/kc58236582/article/details/49618445 1 L1813系统上双U盘设计方案——系统设计 1.1 ...
- Windows 程序自动更新方案: Squirrel.Windows
Windows 程序自动更新方案: Squirrel.Windows 1. Squirrel Squirrel 是一组工具和适用于.Net的库,用于管理 Desktop Windows 应用程序的安装 ...
- spring boot 自动部署方案
现在主流的自动部署方案大都是基于Docker的了,但传统的自动部署方案比较适合中小型公司,下面的方案就是比较传统的自动部署方案. 1.为什么需要自动部署 基于微服务的架构,自动部署显得非常重要.因为每 ...
- eclipse下Android无法自动生成apk文件怎么办?
eclipse下Android无法自动生成apk文件怎么办? 现象:创建android工程后,通过手动build/clean或自动build均无法在bin文件夹下生成.apk文件 解决方法:进入win ...
随机推荐
- php读取excel(支持03,07)
需要用到PHPExcel这个类 附上代码 //phpExcel读取excel内容 header("Content-Type:textml;charset=utf-8"); //引用 ...
- DB-概念-同义词:同义词/Synonym
ylbtech-DB-概念-同义词:同义词/Synonym 同义词的概念 :英文(synonym)是指向其它数据库表的数据库指针.同义词有私有(private)和公共(public)两种类型. 1.返 ...
- 取余运算 C和python的区别
今天看书发现python与C的负数取余运算结果不同,查资料理解. 取余运算的算法是相同的 r = a- n*(a/n) n!=0 r是余数,a是被除数,n是除数.n不能为0,否则都会报错. 负数 ...
- 关于tomcat中的三个端口的作用及其相关细节
[一]端口内容 tomcat的端口号相关信息: Tomcat admin port——管理端口,允许你远程配置tomcat HTTP——正常的http协议 AJP——Apache JServ Prot ...
- FTP- Download, upload, Delete & find files
Public Function Func_FTP(Operation,ServerName,UserName,Password,RemoteLocation,LocalLocation) 'Set u ...
- 三种JavaScript 消息框
prompt 提示框 <html><head><script type="text/javascript">function disp_prom ...
- Qt 程序在 Windows 下的发布
本文讨论在 Windows 平台下编译成功的 Qt 程序,如何在未配置 Qt 开发环境的 Windows 平台下独立运行的方法. 经过验证发现,在 Ubuntu 平台下编译成功的程序可在未安装 Qt ...
- springboot 项目启动脚本
springboot项目启动可通过下面的shell脚本启动. startup.sh app=order-service-rest.jar appout=logs/${app/.jar/.out} ap ...
- 命令分析nginx访问日志的用法
awk分析日志常用高级使用命令方法 分析访问日志(Nginx为例) 日志格式: '$remote_addr - $remote_user [$time_local] "$request&qu ...
- css3 实现可以中英切换的导航条
html <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <ti ...