多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > android應用版本更新策略

android應用版本更新策略

來源:程序員人生   發布時間:2016-07-13 10:18:35 閱讀次數:2542次

這里寫圖片描述
開發中對版本進行檢查并更新的需求基本是所有利用必須有的功能,可是在實際開發中有些朋友就容易疏忽1些細節。

版本更新的基本流程:

1般是將本地版本告知服務器服務器經過相干處理睬返回客戶端相干信息,告知客戶端需不需要更新,如果需要更新是強迫更新還是非強迫更新。客戶端得到服務器返回的相干信息后再進1步做邏輯處理。

強迫更新:

1般的處理就是進入利用就彈窗通知用戶有版本更新,彈窗可以沒有取消按鈕其實不能取消。這樣用戶就只能選擇更新或關閉利用了,固然也能夠添加取消按鈕,但是如果用戶選擇取消則直接退出利用。

非強迫更新

1般的處理是在利用的設置中添加版本檢查的操作,如果用戶主動檢查版本則彈窗告知用戶有版本更新。這時候用戶可以取消或更新。

功能實際是比較簡單清晰的,但之所以寫這篇文章,是由于在我們公司的1個項目中,我把這個模塊分給了1個有著4年工作經驗的哥們編寫,最后這哥們花了2個小時做完了。我還想這哥們寫得挺快,效力很高嘛,結果1測試發現問題很多:
1. 進入首頁前關閉網絡,進入后刷新界面發現強迫更新提示沒有彈窗
2. 再進入其它界面也沒有任何更新提示
3. 在正常更新時點擊肯定更新,沒有判斷網絡狀態(wifi,移動網絡)直接下載apk文件,如果用戶在移動網絡下將耗費非常多的流量,直接影響用戶體驗
4. 下載進程在利用內沒有進度條提示,通知欄也沒有進度提示
5. apk文件下載進程中,如果強迫結束利用,下載被中斷
6. apk如果正常下載下來,彈出了安裝界面,這時候如果用戶取消了安裝回到利用,在需要強迫更新的情況下并沒有再次彈窗禁止用戶進行任何其它操作,失去了強迫更新的意義

首先聲明下,我這絲毫沒有吐槽的意思喲,只是想說作為1個合格的程序員大家最最少需要做到思惟嚴謹這點,在有能力的情況下對用戶體驗能提點建議最好。自己寫的代碼1定要經過嚴格測試再交付,不要期望測試人員幫你測試再去修改,你要知道現在很多公司是沒有專業的測試人員乃至是沒有測試人員的喲。

針對以上問題出現的緣由分析及解決方案以下:

  • 對1,2問題
    很明顯他把檢查更新的工作只寫在了利用的首頁(比如MainActivity)中了,在其它任何界面并沒有檢查更新的操作
  • 解決方案
    每一個界面都需要檢查更新,固然我們不能在每一個Activity中都復制粘貼1樣的代碼。這時候定義1個BaseActivity,所有其它Activity都從它繼承就顯得很有價值了。可以把檢查更新的操作放到BaseActivity的相干方法中,比如放在onResume中,這樣每當顯示1個界面時都將履行檢查更新的操作

  • 對5問題,如果把下載的操作放在了Activity中進行,如果利用意外終止或強迫退出利用,則下載線程也將被終止

  • 解決方案
    可以將下載任務放到Service中履行,這樣即便利用被終止Service1樣有保活機制(startForeground)讓Service的任務有很大的機會繼續得以履行

  • 對6問題,如果檢查更新的操作沒有在Activity的resume時再次履行,則回到Activity自然也就沒有檢查更新并彈窗了

  • 解決方案
    在Activity的onResume中繼續檢查更新,如果是強迫更新則彈窗禁止用戶進行其它操作

  • 對3,4問題,我倒是覺得不是程序問題而是態度問題,實際加入非wifi和進度顯示的功能非常簡單

整體解決方案

  1. 定義Service類,比如VersionUpdateService.java。主要提供版本檢查及文件下載操作
  2. 定義VersionUpdateHelper類,用來使用Service并提供和前臺Activity的交互
    如果大家對Service的使用還有問題(需要頻繁更新前臺ui等),建議大家瀏覽android圖片緊縮上傳系列-service篇這篇文章先做了解。

核心代碼以下:

public class VersionUpdateService extends Service { private LocalBinder binder = new LocalBinder(); private DownLoadListener downLoadListener;//下載任務監聽回調接口 private boolean downLoading; private int progress; private NotificationManager mNotificationManager; private NotificationUpdaterThread notificationUpdaterThread; private Notification.Builder notificationBuilder; private final int NOTIFICATION_ID = 100; private VersionUpdateModel versionUpdateModel; private CheckVersionCallBack checkVersionCallBack;//檢查結果監聽回調接口 public interface DownLoadListener { void begain(); void inProgress(float progress, long total); void downLoadLatestSuccess(File file); void downLoadLatestFailed(); } public interface CheckVersionCallBack { void onSuccess(); void onError(); } ... private class NotificationUpdaterThread extends Thread { @Override public void run() { while (true) { notificationBuilder.setContentTitle("正在下載更新" + progress + "%"); // the label of the entry notificationBuilder.setProgress(100, progress, false); ... } } } private void starDownLoadForground() { //創建通知欄 notificationBuilder = new Notification.Builder(this); ... Notification notification = notificationBuilder.getNotification(); startForeground(NOTIFICATION_ID, notification); } private void stopDownLoadForground() { stopForeground(true); } //履行版本檢查任務 public void doCheckUpdateTask() { //獲得本定版本號 final int currentBuild = AppUtil.getVersionCode(this); //調用版本檢查接口 ApiManager.getInstance().versionApi.upgradeRecords(currentBuild, new RequestCallBack() { @Override public void onSuccess(Headers headers, String response) { versionUpdateModel = JSON.parseObject(response, VersionUpdateModel.class); ... if (checkVersionCallBack != null) checkVersionCallBack.onSuccess(); } @Override public void onError(int code, String response) { ... } }); } public void doDownLoadTask() { starDownLoadForground(); //啟動通知欄進度更新線程 notificationUpdaterThread = new NotificationUpdaterThread(); notificationUpdaterThread.start(); //文件下載寄存路徑 final File fileDir = FolderUtil.getDownloadCacheFolder(); ... downLoading = true; if (downLoadListener != null) { downLoadListener.begain(); } NetManager.getInstance().download(url, fileDir.getAbsolutePath(), new DownloadCallBack() { @Override public void inProgress(float progress_, long total) { ... //履行進度更新 if (downLoadListener != null) downLoadListener.inProgress(progress_, total); } @Override public void onSuccess(Headers headers, String response) { //履行成功回調 ... installApk(destFile, VersionUpdateService.this); } @Override public void onError(int code, String response) { ... //履行失敗回調 } }); } //安裝apk public void installApk(File file, Context context) { ... } }
public class VersionUpdateHelper implements ServiceConnection { private Context context; private VersionUpdateService service; private AlertDialog waitForUpdateDialog; private ProgressDialog progressDialog; private static boolean isCanceled; private boolean showDialogOnStart; public static final int NEED_UPDATE = 2; public static final int DONOT_NEED_UPDATE = 1; public static final int CHECK_FAILD = -1; public static final int USER_CANCELED = 0; private CheckCallBack checkCallBack; public interface CheckCallBack{ void callBack(int code); } public VersionUpdateHelper(Context context) { this.context = context; } public void startUpdateVersion() { if (isCanceled) return; if (isWaitForUpdate() || isWaitForDownload()) { return; } if (service == null && context != null) { context.bindService(new Intent(context, VersionUpdateService.class), this, Context.BIND_AUTO_CREATE); } } public void stopUpdateVersion() { unBindService(); } private void cancel() { isCanceled = true; unBindService(); } private void unBindService() { if (isWaitForUpdate() || isWaitForDownload()) { return; } if (service != null && !service.isDownLoading()) { context.unbindService(this); service = null; } } ... private void showNotWifiDownloadDialog() { final AlertDialog.Builder builer = new AlertDialog.Builder(context); builer.setTitle("下載新版本"); builer.setMessage("檢查到您的網絡處于非wifi狀態,下載新版本將消耗1定的流量,是不是繼續下載?"); builer.setNegativeButton("以后再說", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ... //如果是強迫更新 exit app if (mustUpdate) { MainApplication.getInstance().exitApp(); } } }); builer.setPositiveButton("繼續下載", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); service.doDownLoadTask(); } }); ... } @Override public void onServiceConnected(ComponentName name, IBinder binder) { service = ((VersionUpdateService.LocalBinder) binder).getService(); service.setCheckVersionCallBack(new VersionUpdateService.CheckVersionCallBack() { @Override public void onSuccess() { VersionUpdateModel versionUpdateModel = service.getVersionUpdateModel(); //EventBus控制更新紅點提示 EventBus.getDefault().postSticky(versionUpdateEvent); if (!versionUpdateModel.isNeedUpgrade()) { if(checkCallBack != null){ checkCallBack.callBack(DONOT_NEED_UPDATE); } cancel(); return; } if (!versionUpdateModel.isMustUpgrade() && !showDialogOnStart) { cancel(); return; } if(checkCallBack != null){ checkCallBack.callBack(NEED_UPDATE); } final AlertDialog.Builder builer = ...//更新提示對話框 builer.setPositiveButton("立即更新", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); if (NetUtil.isWifi(context)) { service.doDownLoadTask(); } else { showNotWifiDownloadDialog(); } } }); //當點取消按鈕時進行登錄 if (!versionUpdateModel.isMustUpgrade()) { builer.setNegativeButton("稍后更新", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.cancel(); cancel(); if(checkCallBack != null){ checkCallBack.callBack(USER_CANCELED); } } }); } builer.setCancelable(false); waitForUpdateDialog = builer.create(); waitForUpdateDialog.show(); } @Override public void onError() { unBindService(); ... } }); service.setDownLoadListener(new VersionUpdateService.DownLoadListener() { @Override public void begain() { VersionUpdateModel versionUpdateModel = service.getVersionUpdateModel(); if (versionUpdateModel.isMustUpgrade()) { progressDialog = ...//生成進度條對話框 } } @Override public void inProgress(float progress, long total) { ...//更新進度條 } @Override public void downLoadLatestSuccess(File file) { ...//履行成功處理 unBindService(); } @Override public void downLoadLatestFailed() { ...//履行失敗處理 unBindService(); } }); service.doCheckUpdateTask(); } ... }

最后,使用方式還是非常簡單的。在BaseActivity中使用:

private VersionUpdateHelper versionUpdateHelper; @Override protected void onResume() { super.onResume(); if(versionUpdateHelper == null) versionUpdateHelper = new VersionUpdateHelper(this); versionUpdateHelper.startUpdateVersion(); } @Override protected void onPause() { super.onPause(); if(versionUpdateHelper != null) versionUpdateHelper.stopUpdateVersion(); }

保證在每進入1個界面和離開界面時都將檢查更新(bindService)和取消檢查(unBindService)。這時候有些朋友可能認為這樣做會不會浪費資源呢?沒有!
1,如果利用是強迫更新,那末在網絡正常情況下進入利用就可以檢查出有新版本,這時候彈窗后用戶不能進入任何操作,沒有機會進入別的界面,所有無進行重復檢查;如果進入利用主頁由于網絡問題,檢查失敗,這時候雖然不會彈窗提示更新,但是如果用戶的網絡恢復落后入任何其它界面都將得到正常的版本更新檢查并彈窗提示
2,如果利用是非強迫更新時,在Helper代碼里進行了以下的判斷:

if (!versionUpdateModel.isMustUpgrade() && !showDialogOnStart) { cancel(); return; }

這里的showDialogOnStart默許為false,也就是說如果不是強迫更新則檢查成功后就當“取消”處理,并在cancel方法中將變量isCanceled修改成true,這樣如果有新的要求想要履行startUpdateVersion()都將被疏忽,注意isCanceled是static全局的。

如果想實現在設置中由用戶手動檢查更新,則只需履行類似以下代碼:
SettingActivity.java

private VersionUpdateHelper versionUpdateHelper; @OnClick(R.id.rl_version_update) public void onClickVersionUpdate(View view) { if(updateTips.getVisibility() == View.VISIBLE){ return; } VersionUpdateHelper.resetCancelFlag();//重置cancel標記 if (versionUpdateHelper == null) { versionUpdateHelper = new VersionUpdateHelper(this); versionUpdateHelper.setShowDialogOnStart(true); versionUpdateHelper.setCheckCallBack(new VersionUpdateHelper.CheckCallBack() { @Override public void callBack(int code) { //EventBus發送消息通知紅點消失 VersionUpdateEvent versionUpdateEvent = new VersionUpdateEvent(); versionUpdateEvent.setShowTips(false); EventBus.getDefault().postSticky(versionUpdateEvent); } }); } versionUpdateHelper.startUpdateVersion(); }

寫在最后

由于代碼較多,且多數代碼和ui相干,所以在文章中很多ui相干或getter和setter方法等非核心代碼并沒有列出。演示代碼中用了EventBus和OkHttp開源控件,具體使用方法望大家自己找相干資料學習。本人打算有空的時候寫個EventBus系列文章,望大家多多關注。
文件下載也是使用的okHttp實現的,大家可以換成任何你熟習的下載框架。VersionUpdateService.java和VersionUpdateHelper.java的完全代碼可以到我的github上下載,由于時間關系并沒有相干用法的完全案例還望見諒,等有時間1定奉上。
如果有任何問題可以在評論中加以發問,謝謝~~

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 欧美jizzhd极品欧美 | 欧美精品一区二区三区视频 | 欧美日韩免费一区二区三区 | 亚欧成人乱码一区二区 | 日韩欧美一区二区久久 | 2021年最新久久久视精品爱 | 国产欧美日韩免费一区二区 | 92看片淫黄大片看国产片 | 成人精品美女隐私漫画 | 久久综合九九亚洲一区 | 亚洲成人偷拍自拍 | 国产免费叼嘿在线观看 | 亚洲伊人成综合成人网 | 亚洲国产精品第一区二区三区 | 色中色资源站 | 国产美女亚洲精品久久久综合91 | 亚洲欧美另类色妞网站 | 中文字幕视频网 | 日韩一本二本 | 美女福利片| 精品视频一区二区三区四区 | 女人aaaaa片一级一毛片 | 免费在线日本 | 欧美羞羞 | 在线视频一本 | 午夜影视福利 | 国产一区亚洲欧美成人 | www.九色.com| 亚洲看看| 欧美性猛交乱大交xxxx | 看亚洲人配人配人种jizz | 国内精品视频成人一区二区 | 亚洲精品国产第一区二区多人 | 日本一区二区视频 | 找国产毛片看 | 成人国产网站v片免费观看 成人国产亚洲 | 免费高清a级毛片在线播放 免费高清不卡毛片在线看 免费高清国产 | 亚洲图片欧美文学小说激情 | 在线满18网站观看视频 | 成人a网站 | 操人视频免费 |