天天看點

versionCode溢出的問題

android應用的版本主要由versionCode和versionName來決定,android系統是根據versionCode來驗證新的apk是否能安裝。如果已安裝高版本的應用,就無法使用覆寫安裝的方式來裝舊的包

之前測試那邊向我回報的一個問題是:Android 5.0的機器,新增了多使用者功能,如果安裝新版本的應用然後删除掉,再裝老版本的,理論上應該是可以裝的(因為已經解除安裝過了),但實際仍可能遇到安裝失敗的情況,告知無法安裝。到設定裡查找應用後,選擇為所有使用者删除,才能将應用解除安裝幹淨。

還有一個問題就是小米的系統,裝置中已安裝舊的應用,當使用新的應用進行覆寫安裝時,應用的icon可能會顯示不正常,重新開機裝置就正常了。

回到正題,需要重點來說一下versionCode和versionName的差別:

versionCode 是一個有符号的整型(signed int),其值的範圍為-2^31  ~ 2^31 – 1,但零、負值沒什麼實際意義,是以一般取1 ~ 2147483647之間的值

最大值為Math.pow(2, 31) – 1 = 2147483647

versionName 是一個字元串,通常我們會使用xx.xx或者xx.xx.xx這樣進行區分,對外也是拿versionName進行宣傳,比如我們釋出了2.0版本,新增xx功能,優化xx

版本的控制問題,通常的做法是出一個新版本時,versionName與versionCode一起提升,這樣能避免很多問題

前面提到versionCode是一個數字,在XML中還是以字元串的形式進行配置的,既然打包嘛,如果使用年/月/日/這樣的形式來标注versionCode感覺是比較理想的,不過這時候要注意它是一個int(可能會溢出的問題)

今天,我們這邊的一個同僚打包,versionCode寫為:20150205001    (2015/02/05/001)其中001表示02/05那天第一次打包,但這裡就遇到一個溢出的出問。的确,配置中寫20150205001編譯、導出包并不會有任何的錯誤,但是如果你拿這個包進行覆寫安裝時,問題來了。直接提示你:已安裝高版本,Why?

明明不是新版本嗎,怎麼變低版本了呢

我們反編譯導出的包,發現AndroidManifest.xml中versionCode的值為-1324631479。什麼原因呢?

原因就在于 20,150,205,001 轉成int時它溢出了,int最大值前面講過是 2,147,483,647 很明顯嘛,既然溢出了它就變成一個負數了,是多少呢? 20150205001>>32 (右移32位) –1324631479

怎麼處理呢?簡單一點的辦法就是”001” 改為 “01”這樣就不會溢出了,那有人會說二位不夠用啊,我覺得一天下來你應該不會打超過99個同版本(versionName)的包吧 

參考資料:

<a href="http://stackoverflow.com/questions/24246143/maximum-length-of-android-versionname-versioncode-manifest/24246191#24246191" target="_blank">Maximum Length of Android versionName / versionCode (Manifest)</a>

<a href="http://bbs.csdn.net/topics/40216116" target="_blank">Java中整數溢出的問題:int i=1000000;i*i為何等于-727379968,Java是如何處理溢出的?</a>

繼續閱讀