Android:实现应用版本更新
〇、前言
應用版本更新作為Android應用的基礎功能是每個應用都必須具有的,這個功能實現起來也有多種方式。前段時間我們項目改版,重新梳理了應用更新的邏輯,功能本身是比較簡單的,但是各種可能的異常情況還是挺多的,特此進行記錄。
一、使用OkHttp實現應用版本更新
主要有三個方法:首先檢測是否有新的版本,然后進行APK文件下載,最后安裝新的APK。
檢測新版本的方法如下:
/*** 檢測是否有新的版本,如有則進行下載更新:* 1. 請求服務器, 獲取數據;2. 解析json數據;3. 判斷是否有更新;4. 彈出升級彈窗或直接進入主頁面*/private void checkVersion() {showLaunchInfo("正在檢測是否有新版本...", false);String checkUrl = "http://localhost:8080/AndroidAPK/AndroidUpdate.json";OkHttpClient okHttpClient = new OkHttpClient();//創建 OkHttpClient 對象Request request = new Request.Builder().url(checkUrl).build();//創建 RequestokHttpClient.newCall(request).enqueue(new Callback() {//發送請求@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {Log.w(TAG, "onFailure: e = " + e.getMessage());mProcess = 30;showLaunchInfo("新版本檢測失敗,請檢查網絡!", true);}@Overridepublic void onResponse(@NotNull Call call, @NotNull Response response) {try {Log.w(TAG, "onResponse: response = " + response);mProcess = 30;final ResponseBody responseBody = response.body();if (response.isSuccessful() && responseBody != null) {final String responseString = responseBody.string();Log.w(TAG, "onResponse: responseString = " + responseString);//解析jsonfinal JSONObject jo = new JSONObject(responseString);final String versionName = jo.getString("VersionName");final int versionCode = jo.getInt("VersionCode");final String versionDes = jo.getString("VersionDes");final String versionUrl = jo.getString("VersionUrl");//本地版本號和服務器進行比對, 如果小于服務器, 說明有更新if (BuildConfig.VERSION_CODE < versionCode) {//本地版本小于服務器版本,存在新版本showLaunchInfo("檢測到新版本!", false);progressBar.setProgress(mProcess);//有更新, 彈出升級對話框showUpdateDialog(versionDes, versionUrl);} else {showLaunchInfo("該版本已是最新版本,正在初始化項目...", true);}} else {showLaunchInfo("新版本檢測失敗,請檢查服務!", true);}} catch (Exception e) {e.printStackTrace();showLaunchInfo("新版本檢測出現異常,請檢查服務!", true);}}});}下載APK文件的方法如下:
private void downloadNewApk(String apkName) {showLaunchInfo("檢測到新版本,正在下載...", false);final File downloadDir = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);if (downloadDir != null && downloadDir.exists() && downloadDir.isDirectory()) {//刪除(/storage/emulated/0/Android/data/包名/files/Download)文件夾下的所有文件,避免一直下載文件堆積File[] files = downloadDir.listFiles();if (files != null) {for (final File file : files) {if (file != null && file.exists() && file.isFile()) {boolean delete = file.delete();}}}}//顯示進度條final ProgressDialog dialog = new ProgressDialog(this);dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);//水平方向進度條, 可以顯示進度dialog.setTitle("正在下載新版本...");dialog.setCancelable(false);dialog.show();//APK文件路徑final String url = "http://localhost:7090/AndroidAPK/" + apkName;Request request = new Request.Builder().url(url).build();new OkHttpClient().newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {e.printStackTrace();String strFailure = "新版本APK下載失敗";showLaunchInfo(strFailure, false);showFailureDialog(strFailure, apkName);dialog.dismiss();}@Overridepublic void onResponse(@NotNull Call call, @NotNull Response response) {try {final ResponseBody responseBody = response.body();if (response.isSuccessful() && responseBody != null) {final long total = responseBody.contentLength();final InputStream is = responseBody.byteStream();final File file = new File(downloadDir, apkName);final FileOutputStream fos = new FileOutputStream(file);int len;final byte[] buf = new byte[2048];long sum = 0L;while ((len = is.read(buf)) != -1) {fos.write(buf, 0, len);sum += len;float downloadProgress = (sum * 100F / total);dialog.setProgress((int) downloadProgress);//下載中,更新進度progressBar.setProgress(mProcess + (int) (downloadProgress * 0.7));}fos.flush();responseBody.close();is.close();fos.close();installAPKByFile(file);//下載完成,開始安裝} else {String strFailure = "新版本APK獲取失敗";showLaunchInfo(strFailure, false);showFailureDialog(strFailure, apkName);}} catch (Exception e) {e.printStackTrace();String strException = "新版本APK下載安裝出現異常";showLaunchInfo(strException, false);showFailureDialog(strException, apkName);} finally {/*正常應該在finally中進行關流操作,以避免異常情況時沒有關閉IO流,導致內存泄露*因為本場景下異常情況可能性較小,為了代碼可讀性直接在正常下載結束后關流*/dialog.dismiss();//dialog消失}}});}安裝新APK的方法如下:
/*** 7.0以上系統APK安裝*/private void installAPKByFile(File file) {showLaunchInfo("新版本下載成功,正在安裝中...", false);Intent intent = new Intent(Intent.ACTION_VIEW);//intent.putExtra("pwd", "soft_2694349");//根據密碼判斷升級文件是否允許更新intent.addCategory(Intent.CATEGORY_DEFAULT);Uri uri = FileProvider.getUriForFile(this, "com.lxb.demo0325.fileProvider", file);//intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);intent.setDataAndType(uri, "application/vnd.android.package-archive");startActivityForResult(intent, REQUEST_INSTALL);}如上,代碼并不難,主要是各種可能的異常判斷,為了代碼的完整性,我將整個應用版本更新Demo進行了上傳:https://github.com/beita08/AppUpdate
其中,服務端配置的更新文件,可以是Json形式的:
{"VersionName":"3.1.1.2","VersionCode":545,"VersionDes":"發現新版本, 趕緊更新吧!","VersionUrl":"ApkName" }參考資料:https://www.cnblogs.com/xiaoxiaoqingyi/p/7003241.html
二、使用三方服務進行應用版本更新
應用版本更新作為通用的統一功能也可以使用三方提供的服務進行,最常用的就是騰訊的bugly。
騰訊Bugly是騰訊為開發者提供的一種三方服務,主要包含有:異常上報、運營統計、應用升級等三大功能,對于我們可以使用其應用升級和異常上報功能,官網地址為:https://bugly.qq.com/v2/。首先使用Bugly功能需要在客戶端集成其相關SDK:
bugly功能介紹:
1、應用升級:
將我們更新的apk文件上傳至bugly后臺,設置下發策略(其中可選強制升級和下發上限等,也可填寫更新說明),客戶端檢測到bugly后臺有新版本就會進行下載。
應用升級官網介紹連接:https://bugly.qq.com/docs/introduction/app-upgrade-introduction/?v=20180709165613
2、異常上報
客戶端集成后,對于線上用戶使用過程中的出現的異常問題,會匯總至bugly后臺自動進行匯總分類,便于分析用戶端出現的問題。(此日志在用戶端設備上),bugly的推出初衷就是匯總異常信息。
異常上報官網介紹連接:https://bugly.qq.com/docs/introduction/bugly-introduction/?v=20181014122344#_3
bugly優缺點分析:
優點:
1、應用升級使用第三方服務后不需要占用我們自己的服務器資源,升級并發量也有保障。
2、異常上報可以監測用戶端異常情況,這部分我們平時自己較難檢測。
缺點:
1、信息安全問題:客戶端需集成相關SDK并且需要將我們的APK文件上傳至三方服務器上;
2、更新應用時平板終端需要連接bugly后臺外網;
3、我們各個地區的apk文件需要進行區分,避免下載時串線(都從bugly后臺下載)。
?
?
?
總結
以上是生活随笔為你收集整理的Android:实现应用版本更新的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 工作137:map函数
- 下一篇: android sina oauth2.