帶有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還原。
