带有commit id的版本描述
git describe可以显示用户友好的版本描述:
$ git describe --tags
0.1.34-3-gab9f2b0
它的含义是:
1、当前HEAD位置前面一个tag是0.1.34。
2、当前HEAD在0.1.34 tag之后3个commit的位置。
3、当前HEAD对应的commit id是ab9f2b0。(g应该表示global,全局唯一的SHA)
参见下面的分支图:
$ git lg -5
* ab9f2b0 - (HEAD, origin/master, origin/HEAD, master) exit with status 0 when t
* c99a2a9 - Merge pull request #210 from egeland/master (9 months ago) <Gabrie
|\
| * 20ebe7a - Added Norwegian strings (9 months ago) <Frode Egeland>
|/
* 388aa1d - (0.1.34) release 0.1.34 (9 months ago) <Gabriel Falcao>
注:
如果HEAD位置刚好有tag,则只显示tag。
版本描述如何传递给应用代码
如果是C/C++,可以在Makefile中定义宏来传递。
那么Java编写的APK如何传递呢?
经过研究,较好的一种方式是通过AndroidManifest.xml中的meta-data。
在AndroidManifest.xml中增加hw_version的meta-data
<application>
<activity>
</activity>
<meta-data android:name="hw_version" android:value="0.1.34-3-gab9f2b0" />
</application>
在Java文件中读取meta-data
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_app);
try {
ApplicationInfo appInfo = this.getPackageManager()
.getApplicationInfo(getPackageName(),
PackageManager.GET_META_DATA);
String hwVersion=appInfo.metaData.getString("hw_version");
((TextView)findViewById(R.id.hw_version)).setText("Apk version is " + hwVersion);
Log.i("MyCamera", "The version of this apk is " + hwVersion);
} catch (Exception ex) {
Log.i("MyCamera", "Get apk version failed.");
}
}
如何在Android编译系统中自动生成hw_version
用sed替换版本号
首先固定在AndroidManifest.xml中默认设置hw_version为no-version。
在编译的时候用sed命令替换成正确的版本描述。
$ sed -n 's/<meta-data android:name="hw_version" android:value=".*"/<meta-data android:name="hw_version" android:value="abcdef"/p' AndroidManifest.xml
<meta-data android:name="hw_version" android:value="abcdef" />
修改Android.mk自动查询版本描述并更新AndroidManifest.xml
在Android.mk中 include $(BUILD_PACKAGE) 之前加上:
LOCAL_HW_VERSION := $(shell git --git-dir=$(LOCAL_PATH)/.git describe --tags)
$(shell sed -i 's/<meta-data android:name="hw_version" android:value=".*"/<meta-data android:name="hw_version" android:value="$(LOCAL_HW_VERSION)"/' $(LOCAL_PATH)/AndroidManifest.xml)
自动生成应用版本号
Android应用的版本号一般定义在AndroidManifest.xml中,以android:versionName="1.1"的形式标识。
修改版本号,一般要修改该xml文件并上库。
参见前面sed替换版本描述的方法,可以根据git仓最近的tag替换versionName。
比如,保留tag和相对tag的commit数量作为版本号:
$ git describe --tags
0.1.34-3-gab9f2b0
如果当前HEAD位置就有tag,则得到的结果类似下面这样:
$ git describe --tags
0.1.34
可以参考下面的sed正则表达式匹配只使用满足条件的tag:(数字.数字.数字,分别为V版本、R版本、C版本)
$ echo "0.1.34-3-gab9f2b0" | sed -n -e "/^[0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}\(-[0-9]\{1,\}-g[0-9a-f]\{7,\}\)\{0,1\}$/p"
0.1.34-3-gab9f2b0
$ echo "0.1.34" | sed -n -e "/^[0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}\(-[0-9]\{1,\}-g[0-9a-f]\{7,\}\)\{0,1\}$/p"
0.1.34
该正则表达式的说明如下:
^ 匹配字符串开始
[0-9]\{1,\} 匹配1个或多个数字
\. 匹配点。
\(-[0-9]\{1,\}-g[0-9a-f]\{7,\}\)\{0,1\} commit相关信息出现0次或者1次。
$ 匹配字符串结束。
为了用户更容易理解,可去掉最后面的commit id,并把相对于tag位置的commit数量以点连接起来,为了避免没有commit id的时候末尾是个点,可总是补上一个0:
$ echo "0.1.34-3-gab9f2b0" | sed -n -e "s/^\([0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}\)\(-\([0-9]\{1,\}\)-g[0-9a-f]\{7,\}\)\{0,1\}$/\1\.0\3/p"
0.1.34.03
当按照上述方式得到的结果不为空,才替换versionName. 把这个思路实现到Android.mk中:
LOCAL_HW_VERSION_NAME := $(shell echo $(LOCAL_HW_VERSION) | sed -n -e "s/^\([0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}\)\(-\([0-9]\{1,\}\)-g[0-9a-f]\{7,\}\)\{0,1\}\$$/\1\.0\3/p")
ifneq (,$(strip $(LOCAL_HW_VERSION_NAME)))
$(shell sed -i 's/android:versionName=".*"/android:versionName="$(LOCAL_HW_VERSION_NAME)"/' $(LOCAL_PATH)/AndroidManifest.xml)
endif
说明:
Makefile中的$需要重复进行转义。
Makefile修改重构优化
这么复杂而且可复用的处理直接写在每个模块的Android.mk中显然是不好的,最好把它提取成函数,需要的地方调用一次即可。
于是,把它提取到 build/core/.mk 中,内容如下:
###########################################################
## Modify version info in AndroidManifest.xml
###########################################################
# Usage:
# 1. git tag n.m.x on the significant commit. (n, m, x are digitals)
# 2. call $(modify-hw-version) in Android.mk
# 3. make sure there is android:versionName or hw_version meta-data in AndroidManifest.xml
define modify-hw-version
$(eval $(generate-hw-version))
endef
# 1. LOCAL_HW_VERSION is like 0.1.34-3-gab9f2b0,
# 0.1.34 is tag name,
# 3 is commit count from the tag,
# ab9f2b0 is the current commit id.
#
# 2. LOCAL_HW_VERSION_NAME is like 0.1.34.03
define generate-hw-version
$(eval LOCAL_HW_VERSION := $(shell git --git-dir=$(LOCAL_PATH)/.git describe --tags))
$(shell sed -i 's/<meta-data android:name="hw_version" android:value=".*"/<meta-data android:name="hw_version" android:value="$(LOCAL_HW_VERSION)"/' $(LOCAL_PATH)/AndroidManifest.xml)
$(eval LOCAL_HW_VERSION_NAME := $(shell echo $(LOCAL_HW_VERSION) | sed -n -e "s/^\([0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}\)\(-\([0-9]\{1,\}\)-g[0-9a-f]\{7,\}\)\{0,1\}\$$/\1\.0\3/p"))
ifneq (,$(strip $(LOCAL_HW_VERSION_NAME)))
$(shell sed -i 's/android:versionName=".*"/android:versionName="$(LOCAL_HW_VERSION_NAME)"/' $(LOCAL_PATH)/AndroidManifest.xml)
endif
endef
此方案可圆满解决版本号自动生成的问题,但编译后AndroidManifest.xml被修改。这可能影响后续的git操作。
最好能有编译的后处理,把AndroidManifest.xml还原。