一、重要性

早年因为软件主要自己负责自己的分发、升级等方面,所以版本号也相当自由,各家都有不同的规范。但是近年来移动设备崛起,App Store这样的应用商店集中分发成了主流。以升级为例,应用商店会负责检查消费者手机上应用的版本,并和商店里面最新的版本比较,如果商店里面的版本比较新,消费者手机上的版本比较旧,就会提醒消费者升级。

这就涉及到如何识别新、旧的问题。

对于计算机来说,最可靠的判断方式就是数字,数字有很多好处:程序容易判断、格式简单不容易出错、肉眼容易识别等。所以Google要求每个应用都要在APK安装包中记录这个安装包的[VersionCode],只要拿到这个APK文件,就可以知道它对应的[VersionCode]是多少,应用商店就会以这个[VersionCode]为准,来判断版本。安装包的[VersionCode]数字越大就越新。这样开发者在开发过程中,每有一个新版本只要加大一点这个数字就可以了。比如第一个版本的[VersionCode]是1,第二个版本是2。因为开发者可能每天可能会产生多个没有发布的版本,所以这个数字会增长的很快。

版本控制对于发布新版本和开发中的版本维护有着关键性的作用,版本控制之所以重要的原因如下:

  1. 用户在安装APP的时候需要知道详细的版本信息,并且在对已有版本进行升级的时候,能否正确安装新版本都和版本控制有关。
    比如:当手机中安装APP的versionCode=1,升级更新的版本号是2(versionCode=2),此时APP可以正常安装更新。反之,如果手机中当前APP版本号是2,升级的或者从其他渠道获取的同一APP的版本号为1,此时替换安装就会失败。这种情况就是说,同一个APP低版本是不能直接覆盖安装手机中已存在的高版本应用(通过版本号versionCode来判断)。这样就给我们在应用升级维护过程中,提高了软件的可维护性和安全性
  2. 对于其他应用想要搜索或者调用指定版本号和版本名称的应用来说,有了可靠的保证
  3. 对于我们自己的版本更新系统或者第三方的APP市场,也通过版本号和版本名称来找到和用户终端设备或者终端应用相匹配的 APP 展示给用户。对于第三方APP市场来说,这个版本更为关键的是,决定对用户下载下来之后的兼容性判断起到一定管控作用

所以版本控制不能忽视,我们可以通过有效的版本控制来管控我们发布到市场的应用,以便得到更好的用户体验。

二、Android中版本属性

Google为APK定义了两个关于版本属性:VersionCode和VersionName,他们有不同的用途。下面是一个Manifest.xml文件样例:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.app"
    android:versionCode="1"
    android:versionName="1.0" >
    <application
        android:icon="@drawable/ic_launcher"
        android:theme="@style/AppTheme" >
        ...            
    </application>
</manifest>

2.1 VersionCode

根据上面的描述,版本号(versioncode)是相对比较重要的一个属性。对消费者不可见,仅用于应用市场、程序内部识别版本,判断新旧等用途。

versionCode是一个Integer类型的值。所以大家在设置的时候,不要将versionCode设置的太大,最好不要超过Integer的取值范围(当然一般也是不会超过的),一般大家在发布自己的第一个应用到市场的时候,版本取值为1(versionCode=1),这也是目前典型和普遍的做法。

然后,每次发布更新版本时可以递增versionCode的值。上面描述版本控制重要性时也描述过,一个新版本的应用的versionCode不能小于之前旧版本的versionCode值,否则进行替换更新升级时会出错,系统提示无法安装。当然,这也不是强制的,只是正式发布应用时,建议必须考虑的问题。

2.2 VersionName

展示给消费者,消费者会通过它认知自己安装的版本,平时提到的版本号都是说VersionName。

这是一个值为String类型的属性,一般和VersionCode成对出现。VersionCode是方便程序开发者运行和维护Application而设置的一个有效的值。versionName是一个版本的描述,给用户看的,也是用户放在各个第3方平台上提供给使用者看的一个版本名,可以说是对VersionCode的解释和描述。

三、形式——四段式

Android版本号分为三段式和四段式数字形式。

四段式是一种常见软件版本号的形式是major.minor.maintenance.build,用“.”进行区隔:

  • major是主版本号,一般在软件有重大升级时增长
  • minor是次版本号、子版本号,一般在软件有新功能时增长
  • maintenance是维护版本、阶段版本号,一般在软件有主要的问题修复后增长
  • build是构建版本或者日期版本号加希腊字母版本号,一般只要软件被重新编译过就会增长。希腊字母版本号共有5种,分别为:base、alpha、beta、RC、release。例如:1.1.1.051021_beta。

3.1 版本号修改规则

⑴ 主版本号(1)
当功能模块有较大的变动,比如增加多个模块或者整体架构发生变化。此版本号由项目决定是否修改。

⑵ 子版本号(1)
相对于主版本号而言,子版本号升级对应的是软件功能有一定的增加或变化,比如增加了对权限控制、增加自定义视图等功能。此版本号由项目决定是否修改。

⑶ 阶段版本号(1)
一般是 Bug 修复或是一些小的变动,要经常发布修订版,时间间隔不限,修复一个严重的bug即可发布一个修订版。此版本号由项目经理决定是否修改。

⑷ 日期版本号(051021)
用于记录修改项目的当前日期,每天对项目的修改都需要更改日期版本号。此版本号由开发人员决定是否修改。

⑸ 希腊字母版本号(beta)
此版本号用于标注当前版本的软件处于哪个开发阶段,当软件进入到另一个阶段时需要修改此版本号。此版本号由项目决定是否修改。

3.2 软件版本阶段说明

⑴ Base:
此版本表示该软件仅仅是一个假页面链接,通常包括所有的功能和页面布局,但是页面中的功能都没有做完整的实现,只是做为整体网站的一个基础架构。

⑵ α(Alpha)版:内测版。
软件的初级版本,表示该软件在此阶段以实现软件功能为主,通常只在软件开发者 内部交流,或者专业测试人员测试用,一般而言,该版本软件的Bug较多,需要继续修改,是测试版本。测试人员提交Bug经开发人员修改确认之后,发布到测试网址让测试人员测试,此时可将软件版本标注为alpha版。

⑶ β(Beta)版:公测版。
该版本相对于α版已有了很大的改进,消除了严重的错误,但还是存在着一些缺陷,需要经过多次测试来进一步消除,此版本主要的修改对像是软件的UI,供专业爱好者大规模测试用。

⑷ RC 版:
是 Release Candidate 的缩写,意思是发布倒计时,候选版本,该版本已经相当成熟了,完成全部功能并清除大部分的BUG,基本上不存在导致错误的BUG,与即将发行的正式版相差无几。

⑷ Release 版:
该版本意味“最终版本”,在前面版本的一系列测试版之后,终归会有一个正式版本,是最终交付用户使用的一个版本。该版本有时也称为标准版。一般情况下,Release不会以单词形式出现在软件封面上,取而代之的是符号(R)。

3.3 版本号修改举例说明

比如版本号为:1.0.0.0321_alpha ,此时为内部测试阶段

⑴ 开发人员修复了测试人员提交的bug并经测试人员测试验证关闭bug之后,发布到外网时,此时就进入了软件的下一个阶段,版本号可改为:1.0.0.0321_beta ,如当前日期跟上一个版本号的日期不一样,版本号可改为:1.0.0.0322_beta。

⑵ 如果修复了一些重大Bug 并按照流程发布到外网时就可发布一个修订版,如1.0.1.0322_beta,日期为发布的当前日期。

⑶ 如果对软件进行了一些功能上的改进或增强,进行了一些局部变动的时候要修改次版本号,如:1.1.0.0322_beta(上一级有变动时,下级要归零)。

⑷ 当功能模块有较大变动,增加模块或整体架构发生变化时要修改主版本号,如新增加了退款功能,则版本号要改为:2.0.0.0322_beta 。

⑸ 紧急情况:如果bug比较紧急可跳过一般流程,由开发人员尽快修复bug,测试确认之后直接发布该版本的beta版。

3.4 文档

3.4.1 文件命名规范

文件名称由四部分组成:第一部分为项目名称,第二部分为文件的描述,第三部分为当前软件的版本号,第四部分为文件阶段标识加文件后缀,例如:项目外包平台测试报告1.1.1.051021_beta_b.xls,此文件为项目外包平台的测试报告文档,版本号为:1.1.1.051021_beta。

如果是同一版本同一阶段的文件修改过两次以上,则在阶段标识后面加以数字标识,每次修改数字加1,项目外包平台测试报告1.1.1.051021_beta_b1.xls。

当有多人同时提交同一份文件时,可以在阶段标识的后面加入人名或缩写来区别,例如:项目外包平台测试报告 1.1.1.051021_beta_b_LiuQi.xls。

当此文件再次提交时也可以在人名或人名缩写的后面加入序号来区别,例如:项目外包平台测试报告1.1.1.051021_beta_b_LiuQi2.xls。

3.4.2 版本号的阶段标识

软件的每个版本中包括11个阶段,详细阶段描述如下:
阶段名称 阶段标识
需求控制 a
设计阶段 b
编码阶段 c
单元测试 d
单元测试修改 e
集成测试 f
集成测试修改 g
系统测试 h
系统测试修改 i
验收测试 j
验收测试修改 k

四、形式——三段式

版本号格式:X.Y.Z (主版本号.次版本号.修订号)

  1. 语义化版本控制的软件必须定义公共 API。基于API才可以精确定义版本号的走向
  2. 版本号必须采用 X.Y.Z 的格式, 其中 X、Y 和 Z 为非负的整数,且禁止在数字前方补零。X 是主版本号、Y 是次版本号、而 Z 为修订号。每个元素必须以数值来递增。例如:1.9.1 -> 1.10.0 -> 1.11.0。
  3. 标记版本号的软件发行后,禁止改变该版本软件的内容。任何修改都必须以新版本发行。
  4. 主版本号为零(0.y.z)的软件处于开发初始阶段,一切都可能随时被改变。这样的公共 API 不应该被视为稳定版。
  5. 1.0.0 的版本号用于界定公共 API 的形成。这一版本之后所有的版本号更新都基于公共 API 及其修改内容。
  6. 修订号 Z(x.y.Z > 0)必须在只做了向下兼容的修正时才递增。这里的修正指的是针对不正确结果而进行的内部bug fix。
  7. 次版本号 Y(x.Y.z > 0)必须在有向下兼容的新功能出现时递增。在任何公共 API 的功能被标记为弃用时也必须递增。也可以在内部程序有大量新功能或改进被加入时递增。而每当次版本号递增时,修订号必须归零。
  8. 主版本号 X(X.y.z > 0)必须在有任何不兼容的修改被加入公共 API 时递增。其中可以包括次版本号及修订级别的改变。每当主版本号递增时,次版本号和修订号必须归零。

五、常见问题的解决方案

5.1 同一个版本号,对应了多个VersionCode怎么办

这种情况很常见,比如说新版本发布之后,某个商店反馈说存在xxx问题,需要修复、定制等等操作,于是商务找工程师出了个新版本,考虑到是小版本升级,版本号没变化,但是VersionCode已经变了。

可能遇到的问题:如果这个新版只在部分商店上线,就会出现都是3.1版,A商店的版本其实比B商店的新。已经安装了新版本的用户,还会被提示升级,这时候用户会困扰,为什么我装了3.1还要升级到3.1?部分商店为了最新会抓包,导致渠道包流窜,影响运营监控和分析。

解决方案:版本号应该和VersionCode一起涨,而且一旦发布新版本,就在所有渠道上架新版。

5.2 发布了一个VersionCode错误的版本怎么办?

有时候因为工程师不小心,发布了一个VersionCode过大的版本,比如1.1.1.20版本的VersionCode写成了111,而1.1.1.27版本的VersionCode写成了11127,但是后面发布1.1.2版希望延续旧的VersionCode,用112。

可能遇到的问题:1.1.1.27版的用户将无法获得1.1.2版本的升级,因为在程序看来1.1.1.27版本是比较新的,同时,已经使用了1.1.2版本的用户,可能会收到旧版本的升级提示,比并降级回旧版

解决方案:其实很简单,因为VersionCode对最终用户是不可见的,只要增加就好了,上文的例子,新版VersionCode直接取11200就齐活了。

5.3 发出去的应用有Bug要换回旧版,怎么操作?

偶尔会遇到版本已经发布了,第二天突然发现,糟糕,有Bug,用户开始骂了!于是商务同学到各家市场要求退回旧版本。

可能遇到的问题:已经升级到有Bug版本的用户是无法回滚到旧版的,因此这样直接退回旧版本的方式对这些热心升级的用户是非常不负责任的。而且人肉召回的力度实在有限,这个有Bug的版本一定会流传的。

解决方案:最好是不要浪费时间退回旧版,赶紧修复Bug发个新版本(记得加VersionCode),如果Bug比较棘手,暂时无法修复,只能退回旧版本,这时建议把旧版本的VersionCode改大一些后,提交新版本,这样可以保证所有用户都能下载/升级到一个相对可靠的版本。

参考
1、ANDROID版本号和版本名称的重要性介绍
2、VersionCode和VersionName的区别
3、软件版本阶段
4、语义化版本命名——【干货】强烈推荐