日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國(guó)內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁(yè) > php開(kāi)源 > 綜合技術(shù) > android產(chǎn)品研發(fā)(十四)-->App升級(jí)與更新

android產(chǎn)品研發(fā)(十四)-->App升級(jí)與更新

來(lái)源:程序員人生   發(fā)布時(shí)間:2016-08-22 09:18:55 閱讀次數(shù):5009次

轉(zhuǎn)載請(qǐng)標(biāo)明出處:1片楓葉的專欄

上1篇文章中我們講授了android app中的輪詢操作,講授的內(nèi)容主要包括:我們?cè)贏pp中使用輪詢操作的情形,作用和實(shí)現(xiàn)方式等。1般而言我們使用輪詢操作都是通過(guò)定時(shí)任務(wù)的情勢(shì)要求服務(wù)器并更新用戶界面,輪詢操作都有1定的使用生命周期,即在1定的頁(yè)面中啟動(dòng)輪詢操作,然后在特定的情況下關(guān)閉輪詢操作,這點(diǎn)需要我們尤其注意,我們還介紹了使用Timer和Handler實(shí)現(xiàn)輪詢操作的實(shí)例,更多關(guān)于App中輪詢操作的信息,可參考我的:android產(chǎn)品研發(fā)(103)–>App輪詢操作

本文將講授app的升級(jí)與更新。1般而言用戶使用App的時(shí)候升級(jí)提示有兩種方式取得:

  • 1種是通過(guò)App Store獲得

  • 1種是打開(kāi)利用以后提示用戶更新升級(jí)

而更新操作1般是在用戶點(diǎn)擊了升級(jí)按鈕以后開(kāi)始履行的,這里的升級(jí)操作也分為兩種情勢(shì):

  • 1般升級(jí)

  • 強(qiáng)迫升級(jí)

app升級(jí)操作:

  • App Store升級(jí)

在App Store中升級(jí)需要為App Store上傳新版App,我們?cè)谛掳姹就瓿梢院蠖紩?huì)上傳到App Store中,不同的利用市場(chǎng)審核的時(shí)間不同,1般除第1次上傳時(shí)間較長(zhǎng)以外,其余的審核都是挺快的,1般不會(huì)超過(guò)半天(不排除例外情況奧),在審核完成以后就相當(dāng)于完成了這個(gè)利用市場(chǎng)的發(fā)布了,也就是發(fā)布上線了。這時(shí)候候如果用戶安裝了這個(gè)利用市場(chǎng),那末就可以看到我們的App有新版本的升級(jí)提示了。

  • 利用內(nèi)升級(jí)

除可以在利用市場(chǎng)升級(jí),我們還可以在利用內(nèi)升級(jí),在利用內(nèi)升級(jí)主要是通過(guò)調(diào)用服務(wù)器端接口獲得利用的升級(jí)信息,然后通過(guò)獲得的服務(wù)器升級(jí)利用信息與本地的App版本比對(duì),若服務(wù)器下發(fā)的最新的App版本高于本地的版本號(hào),則說(shuō)明有新版本發(fā)布,那末我們就能夠履行更新操作了,否則疏忽掉便可。

利用內(nèi)升級(jí)其實(shí)已有好多第3方的SDK了,常見(jiàn)的友盟,百度App開(kāi)發(fā)工具包都已集成了升級(jí)的功能,部份SDK廠商還提供增量更新的功能。增量更新的內(nèi)容不是我們這里的討論重點(diǎn),想了解更多增量更新的內(nèi)容可參考:淺談Android增量升級(jí)

這里我們先簡(jiǎn)單介紹1下友盟的App升級(jí)功能,友盟其實(shí)已有了App升級(jí)的API,我們只需要簡(jiǎn)單的調(diào)用便可。

  • 友盟更新接口API
/** * 要求友盟更新API,判斷是不是彈出更新彈窗 */ public static void updateVersion(final Activity mContext, final MainActivity.UpdateCallback updateCallback, final boolean isShow) { UmengUpdateAgent.setUpdateListener(new UmengUpdateListener() { @Override public void onUpdateReturned(int updateStatus, UpdateResponse updateInfo) { switch (updateStatus) { //判斷是不是有新版本需要更新 case UpdateStatus.Yes: // has update try { //在線讀取更新參數(shù) String value = MobclickAgent.getConfigParams(mContext, "FORCE_UPDATE_MIXVERSION"); if (value != null && !value.trim().equals("")) { int versionCode = Config.changeVersionNameToCode(value); if (versionCode != 0) { String localVersionName = getVersionName(mContext); int localVersionCode = Config.changeVersionNameToCode(localVersionName); //判斷當(dāng)前版本號(hào)于友盟中的最低版本號(hào),若當(dāng)前版本號(hào)小于最低版本號(hào),則強(qiáng)迫更新,否則非強(qiáng)迫更新 if (localVersionCode <= versionCode) { // 彈窗更新彈窗 updateCallback.onUpdateSuccess(updateInfo); } else { UmengUpdateAgent.setUpdateAutoPopup(true); UmengUpdateAgent.showUpdateDialog(mContext, updateInfo); } } else { UmengUpdateAgent.setUpdateAutoPopup(true); UmengUpdateAgent.showUpdateDialog(mContext, updateInfo); } } else { UmengUpdateAgent.setUpdateAutoPopup(true); UmengUpdateAgent.showUpdateDialog(mContext, updateInfo); } } catch (Exception e) { e.printStackTrace(); } break; case UpdateStatus.No: // has no update if (isShow) { Config.showToast(mContext, "您當(dāng)前使用的友友用車已經(jīng)是最新版本"); } break; } } }); UmengUpdateAgent.setUpdateAutoPopup(false); UmengUpdateAgent.forceUpdate(mContext); UmengUpdateAgent.setChannel(ChannelUtil.getChannel(mContext)); }

以上是友盟的升級(jí)API,在調(diào)用之前需要先繼承友盟的SDK,這樣經(jīng)過(guò)調(diào)用以后我們就能夠通過(guò)友盟實(shí)現(xiàn)更新接口的提示功能了,默許的友盟提供了靜默安裝,更新提示彈窗,強(qiáng)迫更新等幾種,可以根據(jù)本身App的需求來(lái)肯定更新的方式。

如果不喜歡使用第3方的更新方式,我們也能夠通過(guò)調(diào)用服務(wù)器接口的方式實(shí)現(xiàn)自己的更新彈窗提示,主要的邏輯也是通過(guò)判斷服務(wù)器下發(fā)的最新App版本號(hào)與本地版本號(hào)對(duì)照,若服務(wù)器真?zhèn)€App版本號(hào)大于本地的App版本號(hào),則說(shuō)明當(dāng)前App不是最新的版本,需要升級(jí),這里我們簡(jiǎn)單看1下友友用車中自定義的更新接口實(shí)現(xiàn):

/** * 檢測(cè)App是不是需要更新 * * @param mContext * @param isShow 若不需要更新是不是需要彈出文案 */ public static void queryAppBaseVersionInfo(final Activity mContext, final boolean isOneUpdate, final boolean isShow) { try { // 若當(dāng)前網(wǎng)絡(luò)異常,則直接return if (!Config.isNetworkConnected(mContext)) { // 關(guān)閉進(jìn)度條 dismissProgress(isShow); return; } // 控制變量,App更新接口進(jìn)程生命周期中只會(huì)調(diào)用1次 if (isQueryAppUpdated && isOneUpdate) { return; } L.i("開(kāi)始調(diào)用要求是不是需要版本更新的接口...."); ExtInterface.QueryAppBaseVersionInfoNL.Request.Builder request = ExtInterface.QueryAppBaseVersionInfoNL.Request.newBuilder(); request.setClientChannel(CHANNEL_ANDROID); // 查詢最新的版本信息,不需要傳入版本號(hào) // request.setVersionCode(VersionUtils.getVersionName(mContext)); NetworkTask task = new NetworkTask(Cmd.CmdCode.QueryAppBaseVersionInfo_VALUE); task.setBusiData(request.build().toByteArray()); NetworkUtils.executeNetwork(task, new HttpResponse.NetWorkResponse<UUResponseData>() { @Override public void onSuccessResponse(UUResponseData responseData) { if (responseData.getRet() == 0) { try { isQueryAppUpdated = true; ExtInterface.QueryAppBaseVersionInfoNL.Response response = ExtInterface.QueryAppBaseVersionInfoNL.Response.parseFrom(responseData.getBusiData()); if (response.getRet() == 0) { L.i("要求檢測(cè)App是不是更新接口成功,開(kāi)始解析返回結(jié)果"); // 解析檢測(cè)結(jié)果 parserUpdateResule(mContext, response, isShow); } else { if (isShow) { showDefaultNetworkSnackBar(mContext); } } } catch (InvalidProtocolBufferException e) { e.printStackTrace(); if (isShow) { showDefaultNetworkSnackBar(mContext); } } } } @Override public void onError(VolleyError errorResponse) { L.e("要求檢測(cè)更新接口失敗...."); if (isShow) { showDefaultNetworkSnackBar(mContext); } } @Override public void networkFinish() { L.i("要求檢測(cè)更新接口完成...."); // 關(guān)閉進(jìn)度條 dismissProgress(isShow); } }); } catch (Exception e) { e.printStackTrace(); } }

該接口只會(huì)在App打開(kāi)時(shí)調(diào)用1次,判斷App是不是需要更新,然后在要求服務(wù)器成功以后,會(huì)解析要求結(jié)果,我們繼續(xù)看1下我們的解析邏輯:

/** * 解析更新檢查結(jié)果 * * @param response */ private static void parserUpdateResule(Activity mContext, ExtInterface.QueryAppBaseVersionInfoNL.Response response, boolean isShow) { if (mContext == null) { return; } // 判斷是不是需要更新 ExtInterface.AppBaseVersionInfo appBaseVersionInfo = response.getAppBaseVersionInfo(); // 若當(dāng)前更新是不是有效 if (appBaseVersionInfo.getIsDel() == ENEFFECT) { return; } String updateVersionCode = appBaseVersionInfo.getVersionCode(); int updateCode = changeVersionNameToCode(updateVersionCode); int localCode = changeVersionNameToCode(VersionUtils.getVersionName(mContext)); // 本地利用版本號(hào)小于更新的利用版本號(hào),則需要更新 L.i("本地版本號(hào):" + localCode + " " + VersionUtils.getVersionName(mContext) + " 遠(yuǎn)程版本號(hào):" + updateCode + " " + updateVersionCode); if (localCode < updateCode) { // 顯示更新文案 L.i("開(kāi)始顯示更新彈窗..."); showUpdateDialog(mContext, appBaseVersionInfo); } // 不需要更新 else { if (isShow) { Config.showToast(mContext, mContext.getResources().getString(R.string.about_new)); } } }

解析更新接口信息的時(shí)候,會(huì)判斷App的更新操作是普通更新還是強(qiáng)迫更新,若是強(qiáng)迫更新的話,則沒(méi)有取消按鈕,并且更新彈窗不可關(guān)閉。若是普通的更新的話則有暫不更新按鈕,點(diǎn)擊暫不更新更新彈窗會(huì)取消,但是當(dāng)下次打開(kāi)App的時(shí)候,彈窗提示還是會(huì)彈窗。

普通更新包括暫不更新和立即更新兩個(gè)按鈕操作:
這里寫(xiě)圖片描述

強(qiáng)迫更新只有立即更新按鈕,彈窗不可取消:
這里寫(xiě)圖片描述

app更新操作:

app的更新操作就是下載App并安裝了,下面我們還是分兩部份看,利用市場(chǎng)的更新與利用內(nèi)更新

  • App store更新App

在利用市場(chǎng)中更新App很簡(jiǎn)單就是履行簡(jiǎn)單的下載操作,然后順著App的提示,1步步安裝便可,這里沒(méi)有甚么需要注意的地方。

  • 利用內(nèi)更新

利用內(nèi)更新操作主要是當(dāng)用戶點(diǎn)擊了更新按鈕以后履行的,下載,安裝等邏輯,下面我們看1下友友用車?yán)脙?nèi)更新的實(shí)踐。

利用內(nèi)更新主要包括了:普通更新和強(qiáng)迫更新兩種,其中普通更新彈窗可以選擇更新也能夠選擇疏忽,而強(qiáng)迫更新只能選擇更新,并且更新彈窗不可取消。

下面的代碼是履行下載操作的核心邏輯:

/** * 開(kāi)始履行下載動(dòng)作 */ private static void doDownLoad(final Activity mContext, String downloadUrl, final String actionButtonMsg, final boolean isFocusUpdate) { // 強(qiáng)迫更新 if (isFocusUpdate) { DownLoadDialog.updateRela.setVisibility(View.VISIBLE); DownLoadDialog.progressBar.setProgress(0); DownLoadDialog.progressBar.start(); DownLoadDialog.updatePercent.setText("0%"); DownLoadDialog.materialDialog.getPositiveButton().setEnabled(false); DownLoadDialog.materialDialog.getPositiveButton().setText("下載中"); } Config.showToast(mContext, "開(kāi)始下載安裝包......."); // 刪除下載的apk文件 doDeleteDownApk(mContext); L.i("安裝包下載地址:" + downloadUrl); DownloadManager.getInstance().cancelAll(); DownloadManager.downloadId = DownloadManager.getInstance().add(DownloadManager.getDownLoadRequest(mContext, downloadUrl, new DownloadStatusListenerV1() { @Override public void onDownloadComplete(DownloadRequest downloadRequest) { L.i("onDownloadComplete_____..."); // 設(shè)置按鈕是不是可點(diǎn)擊 showPositiveText(false, actionButtonMsg); if (isFocusUpdate) { // 更新進(jìn)度條顯示 DownLoadDialog.updatePercent.setText("100%"); DownLoadDialog.progressBar.stop(); } else { String title = "正在下載友友用車..."; String content = "下載成功"; DownloadNotification.showNotification(mContext, title, content, DownloadNotification.notofyId); // 關(guān)閉通知欄消息 UUApp.notificationManager.cancel(DownloadNotification.notofyId); } // 下載完成,履行安裝邏輯 doInstallApk(mContext); // 退出App UUApp.getInstance().exit(); } @Override public void onDownloadFailed(DownloadRequest downloadRequest, int errorCode, String errorMessage) { L.i("onDownloadFiled______..."); L.i("errorMessage:" + errorMessage); // 設(shè)置按鈕是不是可點(diǎn)擊 showPositiveText(false, actionButtonMsg); if (isFocusUpdate) { // DownLoadDialog.progressBar.stop(); DownLoadDialog.updatePercent.setText("更新失敗"); } else { String title = "正在下載友友用車..."; String content = "下載失敗"; DownloadNotification.showNotification(mContext, title, content, DownloadNotification.notofyId); } } @Override public void onProgress(DownloadRequest downloadRequest, long totalBytes, long downloadedBytes, int progress) { if (lastProgress != progress) { lastProgress = progress; L.i("onProgress_____progress:" + progress + " totalBytes:" + totalBytes + " downloadedBytes:" + downloadedBytes); // 設(shè)置按鈕是不是可點(diǎn)擊 showPositiveText(true, actionButtonMsg); // 強(qiáng)迫更新則更新進(jìn)度條 if (isFocusUpdate) { String content = downloadedBytes * 100 / totalBytes + "%"; float result = progress / (float)100.00; DownLoadDialog.progressBar.setProgress(result); DownLoadDialog.updatePercent.setText(content); } else { String title = "正在下載友友用車..."; String content = downloadedBytes * 100 / totalBytes + "%"; DownloadNotification.showNotification(mContext, title, content, DownloadNotification.notofyId); } } } })); }

這里的下載操作包括了3個(gè)回調(diào)方法:

  • onDownloadComplete()

  • onDownloadFailed()

  • onProgress()

其中onDownlaodComplete方法在下載完成時(shí)回調(diào),onDownloadFailed方法在下載失敗是回調(diào),而onProgress方法則用于刷新下載進(jìn)程,我們?cè)趏nProcess方法中更新通知欄下載進(jìn)度,具體我們可以看1下更新通知欄消息的方法:

/** * 更新通知欄顯示 * @param title * @param content * @param notifyId */ public static void showNotification(Activity mContext, String title, String content, int notifyId) { NotificationCompat.Builder mNotifyBuilder = new NotificationCompat.Builder(mContext) .setSmallIcon(R.mipmap.icon) .setContentTitle(title) .setContentText(content) .setSmallIcon(android.R.drawable.stat_sys_download); Notification notification = mNotifyBuilder.build(); // notification.flags = Notification.FLAG_NO_CLEAR; UUApp.notificationManager.notify(notifyId, notification); }

而在onDownloadFailed方法中,履行的代碼邏輯是提示用戶下載失敗,
而在onDownloadComplete方法中,履行安裝下載apk文件的操作,我們可以繼續(xù)看1下我們是如何履行安裝邏輯的。

/** * 履行安裝apk文件 */ private static void doInstallApk(Activity mContext) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setDataAndType(Uri.fromFile(new File(DownloadManager.getApkPath(mContext))), "application/vnd.android.package-archive"); mContext.startActivity(intent); }

這段代碼會(huì)調(diào)用android的安裝apk程序,這樣我們就履行了下載文件的安裝操作,不同的手機(jī)安裝程序及展現(xiàn)界面略有不同。

總結(jié):

  • App升級(jí)操作分為兩種,在利用市場(chǎng)提示升級(jí)和在利用內(nèi)提示升級(jí),而在利用內(nèi)提示升級(jí)可以繼承第3方升級(jí)API(如:友盟),也能夠自己實(shí)現(xiàn);

  • 利用升級(jí)的提示主要邏輯是根據(jù)服務(wù)器真?zhèn)€APK版本號(hào)與本地的利用版本號(hào)對(duì)照,若服務(wù)器真?zhèn)€利用版本號(hào)高于本地版本號(hào),則說(shuō)明利用需要升級(jí);

  • 利用升級(jí)可以分為普通升級(jí)和強(qiáng)迫升級(jí)兩種,1般不太建議使用強(qiáng)迫升級(jí)(用戶體驗(yàn)很差),除非是1些嚴(yán)重的線上bug;

  • App的更新操作包括下載與安裝兩部份,下載操作時(shí)可以選擇繼承第3方服務(wù),也能夠自己實(shí)現(xiàn)。


另外對(duì)產(chǎn)品研發(fā)技術(shù),技能,實(shí)踐方面感興趣的同學(xué)可以參考我的:
android產(chǎn)品研發(fā)(1)–>實(shí)用開(kāi)發(fā)規(guī)范
android產(chǎn)品研發(fā)(2)–>啟動(dòng)頁(yè)優(yōu)化
android產(chǎn)品研發(fā)(3)–>基類Activity
android產(chǎn)品研發(fā)(4)–>減小Apk大小
android產(chǎn)品研發(fā)(5)–>多渠道打包
android產(chǎn)品研發(fā)(6)–>Apk混淆
android產(chǎn)品研發(fā)(7)–>Apk熱修復(fù)
android產(chǎn)品研發(fā)(8)–>App數(shù)據(jù)統(tǒng)計(jì)
android產(chǎn)品研發(fā)(9)–>App網(wǎng)絡(luò)傳輸協(xié)議
android產(chǎn)品研發(fā)(10)–>不使用靜態(tài)變量保存數(shù)據(jù)
android產(chǎn)品研發(fā)(101)–>利用內(nèi)跳轉(zhuǎn)scheme協(xié)議
android產(chǎn)品研發(fā)(102)–>App長(zhǎng)連接實(shí)現(xiàn)
android產(chǎn)品研發(fā)(103)–>App輪詢操作


本文以同步至github中:https://github.com/yipianfengye/androidProject,歡迎star和follow


生活不易,碼農(nóng)辛苦
如果您覺(jué)得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 性欧美日本| 无码精品一区二区三区免费视频 | 精品伦精品一区二区三区视频 | 国产成人毛片 | 国产精品xxx在线观看www | 日韩精品一区二区三区四区视频 | 黄色小视频免费观看 | 美女视频一区二区三区 | 激情影院免费观看 | 国产福利电影在线 | 成人国产精品久久久 | 欧美成人午夜视频 | 午夜精品 | 午夜视频免费在线观看 | 亚洲另类欧美日韩 | 日本精品一区二区三区视频 | av资源网站 | 国产精品久久久久久久午夜 | 国产精品久久久久国产a级 中文字幕影院 | 99re这里只有精品在线视频 | 欧美日韩精品一区 | 亚洲永久网站 | 国产一区二区在线免费观看 | 男女在线观看 | a在线免费观看 | 国产精品日本一区二区不卡视频 | 亚洲黄色毛片 | 日韩欧美黄色 | 亚洲精品国产精品国自产观看浪潮 | 炮机高潮痉挛哭叫失禁 | 中文字幕一区二区三区在线播放 | 一区二区三区在线电影 | 国产精品久久久久久久久潘金莲 | 精品国产伦一区二区三区免费 | 欧美精品系列 | 国产福利视频在线 | 成人国产精品久久久 | 国产精品久久一区二区三区动漫 | 中文字幕亚洲欧美 | 91久久久久久久 | 91在线区 |