在前幾年,整體移動網絡環境相比現在差很多,加之流量費用又相對較高,因此每當我們發布新版本的時候,一些用戶升級并不是很積極,這就造成了新版本的升級率并不高。而為了解決了這個問題,提出了Smart App Update,即增量更新(也叫做差分升級)。
盡管現在網絡環境有了很大的提升,但一個不爭的事實就是應用越做越大,因此,增量更新在目前的仍然是一種解決APP更新包過大的有效方案。今天,我們就來聊聊增量更新。
增量更新的關鍵在于如何理解增量一詞。來想想平時我們的開發過程,往往都是今天在昨天的基礎上修改一些代碼,app的更新也是類似的:往往都是在舊版本的app上進行修改。這樣看來,增量更新就是原有app的基礎上只更新發生變化的地方,其余保持原樣。
與原來每次更新都要下載完整apk包的做法相比,這樣做的好處顯而易見:每次變化的地方總是比較少,因此更新包的體積就會小很多。比如“師父說”安裝包的體積在6m左右,如果不采用增量更新,用戶每次更新都需要下載大約6m左右的安裝包,而采用增量更新這種方案之后每次只需要下載2m左右的更新包即可,相比原來做法大大減少了用戶下載等待的時間。
增量更新的原理非常簡單,簡單的說就是通過某種算法找出新版本和舊版本不一樣的地方(這個過程也叫做差分),然后將不一樣的地方抽取出來形成所謂的更新補丁(patch),也稱之為差分包。客戶端在檢測到更新的時候,只需要下載差分包到本地,然后將差分包合并至本地的安裝包,形成新版本的安裝包,文件校驗通過后再執行安裝即可。本地的安裝包通過提取當前已安裝應用的apk得到。
如下圖所示:
現在的問題在于如何生成差分包以及合并差分包。這里,我們借助開源庫bsdiff來解決以上兩個問題。首先我們先演示一下差分包的形成與合并。
下載bsdiff_win_exe.zip,解壓到本地。如下圖:
然后,我們先打出一個安裝包,假設為old.apk。對源碼做修改后,再打出一個新的安裝包new.apk。此處old.apk相當于老版本的應用,而new.apk相當于新版本的應用。接下來,我們利用bsdiff來生成差分包patch.patch。
將上面的old.apk和new.apk放入bsdiff解壓后的目錄,然后在控制臺中執行命令bsdiff old.apk new.apk patch.patch,稍等一會便可以生成差分包patch.patch,如下
合并old.apk和patch.patch,生成新的安裝包new.apk。只要此處合并出來的new.apk和上面我們自己打出來的new.apk一樣,那么就可以認為它就是我們需要的新版本安裝包。
我們來看看如何合并。將old.apk和patch.patch放入bsdiff文件夾,合并之前為:
然后執行命令bspatch old.apk new.apk patch.patch,稍等一會之后便可以看到合并出的new.apk.如下:
不出意外,合并而來的new.apk應該和我們自己打出來的new.apk是一模一樣的,這可以通過驗證兩者的md5來認定。
導線在為止,我們已經弄明白增量更行是怎么一回事。下面,我們就以“師父說”為對象進行實踐一把。
客戶端支持增量更新總體和上面的演示差不多,的區別在于客戶端要自行編譯bspatch.c來實現合并差分包,也就是所謂的ndk開發,這里我們首先要下載bsdiff的源碼以及bszip的源碼,以便后面使用。在as中如何進行ndk開放不是本文的重點,因此不做詳細說明。
BsPatchUtil中只有一個natvie方法patch(String oldApkPath,String newApkPath,String patchPath)用于實現增量包的合并:
在實現BsPatchUtil之前,我們需要將bspatch.c以及bzip的相關代碼拷貝到jni目錄下(bzip只保留.h頭文件和.c文件)。并將bspatch.c中的main()方法名修改為executePatch(),并且修改其中bzip的引入頭為#include "bzip2/bzlib.h".目錄結構如下:
注意:上圖當中的em.c是一個空文件,用來避免在window下編譯產生的未知錯誤。
接下來我們就可以在bspatch_util.c中實現相關的代碼了:
至此,大部分工作已經完成了。配置app moudle中的build.gradle中添加ndk配置
接下來,我們編譯試試(ndk環境的配置這里不做說明,自行配置即可),不出意外會遇到以下錯誤:
該問題的解決方法也非常簡單,注釋掉對應文件的main()方法即可。重新編譯,不出意外沒什么問題了。接下來,我們就需要在合適的地方合并差分包了。
上面的過程做完之后,就可以通過BsPatchUtil.patch()來合并當前安裝包和差分包了。
這里,我們假設差分包已經從服務器下載到本地了。
首先來看如何獲取當前安裝包。我們安裝的應用通常在、data/app下,可以通過一下代碼獲取其路徑:
下面就可以通過BsPatchUtil.patch(String oldApkPath,String newApkPath,String pathPath)來進行合并了。此處需要注意兩點:
任何更新包在下載完成后首先要做的就是進行MD5校驗,以便確認該更新包是正規途徑下載而來的。同樣,對于合并之后的更新包,首先要做的事情也是進行MD5校驗,校驗通過之后,再進行安裝:
到現在,增量更新已經完成。現在可以把增量包以及合并之后的安裝包進行刪除了。
增量更新雖讓有效的解決了更新包過大的問題,但是存在以下幾點問題:
本站文章版權歸原作者及原出處所有 。內容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負責,本站只提供參考并不構成任何投資及應用建議。本站是一個個人學習交流的平臺,網站上部分文章為轉載,并不用于任何商業目的,我們已經盡可能的對作者和來源進行了通告,但是能力有限或疏忽,造成漏登,請及時聯系我們,我們將根據著作權人的要求,立即更正或者刪除有關內容。本站擁有對此聲明的最終解釋權。