建立更新線程,跟ui主線程經過message進行交互。
1,去http://version.mygame.com/check.php? channelid=%d&appver=%d&resver=%d獲取客戶端最新版本信息。用curl獲取,代碼以下,至於curl的具體參數,man或者搜索引擎會告訴你答案php
1 static size_t funcGetHttpText(void *ptr, size_t size, size_t nmemb, void *userdata) { 2 size_t retSize = size*nmemb; 3 string* pContent = (string*)userdata; 4 if (pContent) { 5 pContent->append((char*)ptr, retSize); 6 } return retSize; 7 } 8 CURLcode getHttpText(const string& strUrl, string& strHttpText) { 9 CURL* pCurl = curl_easy_init(); 10 if (!pCurl) { 11 return CURL_LAST; 12 } 13 strHttpText.clear(); 14 curl_easy_setopt(pCurl, CURLOPT_CONNECTTIMEOUT, 30); 15 curl_easy_setopt(pCurl, CURLOPT_NOSIGNAL, 1); 16 curl_easy_setopt(pCurl, CURLOPT_FORBID_REUSE, 1); 17 curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 0L); 18 curl_easy_setopt(pCurl, CURLOPT_URL, strUrl.c_str()); 19 curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, funcGetHttpText); 20 curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, &strHttpText); 21 CURLcode err = curl_easy_perform(pCurl); 22 if (err == CURLE_OK) { 23 int sz = 0; 24 curl_easy_getinfo(pCurl, CURLINFO_HTTP_CODE, &sz); 25 if ((sz != 200) && (sz != 206)) { 26 //ok or not modify 27 err = CURL_LAST; 28 } 29 } 30 curl_easy_cleanup(pCurl); 31 return err; 32 }
解析返回的字符串。
1:大版本更新,彈出對話框,提示須要進行大版本更新,用戶能夠選擇」更新」,」取消」。取消後就退出app,點擊更新,進入下面流程。
Android:經過返回的url下載相應的apk,並進行重裝(重裝只針對app,不會重置資源),
Ios: AdHoc,經過代碼打開url的方式進行更新。代碼以下html
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"itms-services://?action=download-manifest&url==https://raw.githubusercontent.com/xxxxxhttp.plist"]];
AppStore:則打開AppStore的app進行更新,代碼以下git
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@" http://itunes.apple.com/gb/app/yin/idxxxxxxxx?mt=8 "]];
此時會跳出當前應用,跳轉到appstore的應用詳情頁。
2:本地資源版本號爲0,下載初始包。3:本地資源版本>0,則下載差別包
判斷本地已下載的臨時文件大小和外網文件的大小是否相同,若是不相同,則斷點下載外網文件。Curl支持斷點下載,代碼以下github
1 char rangBuf[32] = { 0 }; 2 sprintf(rangBuf, "%d-", nRangeFrom); 3 curl_easy_setopt(pCurl, CURLOPT_RANGE, rangBuf);
另外,下載須要判斷3g環境的問題,若是在3g環境下,下載的文件超過必定大小(好比30M),則提示玩家是否下載,玩家自行選擇是否下載。由於咱們下載模塊是多線程的,主線程和多線程經過mutex進行通訊。
下載線程:web
1 while (1) { 2 this_thread::sleep_for(chrono::milliseconds(50)); 3 std::unique_lock<std::mutex> locker(m_mtxConfirm); 4 if (m_eUpdateConfirm == UpdateImplConfirm::UPDATE_UNKNOW) { 5 this_thread::yield(); 6 } else { 7 break; 8 } 9 } 10 if (m_eUpdateConfirm == UpdateImplConfirm::UPDATE_REJECT) { //拒絕更新 11 postMessage(new UserRejectMessage(UpdateState::eUpdateStateDownloadFile)); 12 m_eUpdateConfirm = UpdateImplConfirm::UPDATE_UNKNOW; 13 return CURL_LAST; 14 }
UI:服務器
1 void ConfirmContinue() { 2 std::lock_guard<std::mutex> autoLock(m_mtxConfirm); 3 m_eUpdateConfirm = UpdateImplConfirm::UPDATE_CONTINUE; 4 } 5 void ConfirmReject() { 6 std::lock_guard<std::mutex> autoLock(m_mtxConfirm); 7 m_eUpdateConfirm = UpdateImplConfirm::UPDATE_REJECT; 8 }
下載完成後,文件大小和md5進行比較,若是不一樣。。。則刪除文件,從新下載。
比較成功後,解壓文件到writable目錄,讀取index文件進行數據解析,將追加的文件,覆蓋的文件拷貝到資源目錄進行覆蓋,刪除文件的,則把資源目錄的相應文件進行刪除。檢查資源,遍歷本地資源文件進行md5對比,若是不相同,則去外網下載散文件進行覆蓋。清理臨時目錄,刪除index文件。資源更新完成。
4. 資源版本大於0,而且跟服務器資源版本匹配,無需更新。
Other,出錯【服務器timeout,返回錯誤,==】,顯示「重試」按鈕可重試。多線程
【原創】我所理解的自動更新-概要
【原創】我所理解的自動更新-環境搭建和協議制定
【原創】我所理解的自動更新-外網web服務器配置
【原創】我所理解的自動更新-APP發佈與後臺發佈
【原創】我所理解的自動更新-資源打包流程
【原創】我所理解的自動更新-客戶端更新流程
【原創】我所理解的自動更新-知識點講解app