Android App的版本升級(迭代/更新)
為了修復bug和拓展功能,app是需要不斷升級和維護的。推薦一個我寫的app更新庫——VersionUpdater,該庫將版本升級的通用程式碼封裝起來,並將其和版本更新時的UI提示剝離開來,使用者只需處理自己的UI提示即可。
郭大俠粉絲之眾,令在下敬仰。其中不乏學生黨。因此,先做些知識鋪墊:
①先說說VersionCode和VersionName
//內部版本號,使用者不可見,用於應用市場、android系統及自身程式內部,是整型值(便於不同版本間比較) versionCode 2 //外部版本標識,僅用於展示給使用者看,讓使用者對版本有個感性的認知,是字串值 versionName "1.0.1"
每次釋出新版本,都要提升下VersionCode的值,VersionName也要做出相應修改。
曾經,我的幾個同事爭論VersionName應該是兩位(1.0)還是三位的(1.0.0),其實這個沒有硬性規定,位數多的話,對於更新頻繁和維護週期長的應用,不至於短時間內版本號就升到很高。例如QQ手機版的版本號就是四位的。所以版本名稱位數,視專案的需要靈活而定。
②伺服器通常會提供一個上傳平臺,供我們上傳新版apk的版本資訊及apk檔案
③app執行時,通過後端人員提供的介面獲取最新的版本資訊後與本地比較,若高於本地版本,則表示需要升級,下載最新apk檔案到本地。app會自動發起檢測,也會提供使用者手動檢測的功能。
獲取最新版本資訊的介面返回的json資訊大致是這樣的:
...
{
"VersionCode": 2,
"VersionName": "1.0.1",
"VersionInfo": "①藍芽列印優化
"DownLoadUrl": "http://xxxxxxxx/AppFolders/20180203/PPGSender_v1.0.1.apk",
"ForceUpdate": 0
}
...
其中包含了版本號、版本名稱、更新資訊、是否強制更新、最新apk檔案的下載地址。出於職業操守,公司域名用xxxxxxx代替。
獲取本地版本號,
public static int localVersionCode(Context context) { int versionCode = 1; try { versionCode = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return versionCode; }
也可以簡單地使用BuildConfig.VERSION_CODE,Gradle會在自動生成地BuildConfig類裡生成版本號、版本名稱、包名、構建型別等資訊。
④下載apk,建議使用DownloadManager。
它是google提供的,專門用於後臺長時間下載檔案的類,屬於系統級服務。你不必編寫複雜的下載程式碼,也不必做其他特殊處理,比如,如果我們自己實現下載apk,為了避免下載執行緒被殺死(因為下載apk相對而言是“漫長的”),需開啟Service來執行下載執行緒。一言而蔽之,你通過其他方式實現下載apk的所有功能,DownloadManager都可以高效、便利地提供,此外,其另有獨到之處,比如,可隨時查詢下載的狀態、進度,當網路斷開或裝置重啟導致下載暫停時,待網路恢復或裝置開機時自動恢復。
//獲取DownloadManager物件
DownloadManager downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
//構造apk下載地址的Uri物件
Uri apkUri = Uri.parse("http://xxxxxxxx/AppFolders/20180203/PPGSender_v1.0.1.apk");
//建立一個下載任務
DownloadManager.Request request = new DownloadManager.Request(apkUri)
//設定檔案的儲存位置
.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "PPGSender_v1.0.1.apk")
//下載時,狀態列會出現一個通知條,設定其展示模式
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
//設定通知條的標題
.setTitle("配送員");
//將下載任務加入執行佇列,返回唯一id,標識該任務,用於之後進行查詢操作等
final long downloadId = downloadManager.enqueue(request);