增量更新
概述
簡(jiǎn)單點(diǎn)來(lái)說(shuō)就是兩個(gè)文件:old和new死嗦,可通過(guò)差分工具生成它們的差分包patch,當(dāng)我們需要時(shí)粒氧,再可以通過(guò)另外一個(gè)合成工具在只有old和patch的情況下越除,恢復(fù)生成new文件。這在Android中有什么用呢外盯?它的應(yīng)用場(chǎng)景很廣泛摘盆,拿一個(gè)常見(jiàn)的場(chǎng)景來(lái)舉例,利用這個(gè)技術(shù)饱苟,可以省流量更新我們手機(jī)上已安裝的App孩擂,目前各大應(yīng)用市場(chǎng)基本都實(shí)現(xiàn)增量更新。我們安裝在手機(jī)上的App在我們的存儲(chǔ)卡上都保留有對(duì)應(yīng)的安裝包箱熬,可以理解為old文件类垦,它位于“/data/app/”文件夾下狈邑。當(dāng)我們進(jìn)行版本迭代時(shí),會(huì)上傳給應(yīng)用市場(chǎng)一個(gè)完整的安裝包蚤认,應(yīng)用市場(chǎng)會(huì)更據(jù)以前的安裝包跟最新的安裝包生成對(duì)應(yīng)的差分包對(duì)用戶進(jìn)行下發(fā)米苹,在用戶端再進(jìn)行差分包與原有版本的合成,達(dá)到省流量的目的砰琢。當(dāng)然這其中過(guò)程中還涉及到對(duì)文件完整性MD5校驗(yàn)與簽名校驗(yàn)蘸嘶,以及可能出現(xiàn)差分包比原始包更大的情況,需要采取合適的下發(fā)策略陪汽。不僅是應(yīng)用市場(chǎng)训唱,我們的應(yīng)用內(nèi)更新也可以采取相同方案。此處不再贅述掩缓。
增量更新與全量更新
增量更新 就是根據(jù)歷史某一個(gè)節(jié)點(diǎn)和最新的一個(gè)節(jié)點(diǎn)雪情,對(duì)二者進(jìn)行一個(gè)差分包的生成,然后再合成的一個(gè)方案你辣。通常我們?cè)诎l(fā)布某一版本的App時(shí)巡通,前面已經(jīng)發(fā)布了很多的版本,服務(wù)端可根據(jù)最近的幾個(gè)版本分別做一下差分包進(jìn)行下發(fā)舍哄,更遠(yuǎn)的版本可不用考慮宴凉,直接給一個(gè)完整的安裝包。
全量更新 可以理解為我們直接給一個(gè)完整的安裝包表悬,當(dāng)我們生成的差分包文件很大或者版本太多弥锄,差分包的管理太繁瑣時(shí),可采用全量更新策略
增量更新與熱修復(fù)
很多人對(duì)增量更新與熱修復(fù)的概念比較模糊蟆沫,這里著重強(qiáng)調(diào)一下籽暇,增量更新是在版本更新時(shí),根據(jù)差分包生成一個(gè)新的安裝包然后再安裝饭庞,會(huì)有一個(gè)安裝的過(guò)程戒悠。熱修復(fù)是用來(lái)修復(fù)bug的,比如QQ控件熱修復(fù)方案舟山,利用dx命令對(duì)某個(gè)出現(xiàn)bug的類打包成dex補(bǔ)丁包绸狐,然后再利用類加載機(jī)制,通過(guò)hook技術(shù)替換已加載的類達(dá)到修復(fù)的目的累盗,這個(gè)過(guò)程是無(wú)感知的寒矿,不會(huì)重新安裝apk,本質(zhì)上安裝在手機(jī)里的還是原來(lái)版本的apk。
常用差分若债、合成工具
網(wǎng)上有文章對(duì)BSDiff/Patch符相、HDiffPatch和XDelta三種差分包實(shí)現(xiàn)方案做對(duì)比測(cè)試,在Android APK的差分更新實(shí)現(xiàn)上拆座,XDelta差分方案實(shí)現(xiàn)是最優(yōu)的主巍。但是BSDiff/Patch 實(shí)現(xiàn)方案是最多的冠息,網(wǎng)上一大堆都是這個(gè)方案的實(shí)現(xiàn),Android系統(tǒng)也整合了這個(gè)實(shí)現(xiàn)孕索,所以這里也使用它作為實(shí)例講解怎么使用逛艰。
BSDiff
它是基于二進(jìn)制來(lái)比較兩個(gè)文件的大小,與文件格式無(wú)關(guān)搞旭,所以生成的安裝包大小也不穩(wěn)定散怖。官網(wǎng)下載網(wǎng)址為
http://www.daemonology.net/bsdiff/
下載完后可以看到如下文件
在window環(huán)境下可以通過(guò)CLion來(lái)編譯生成exe,當(dāng)然用vs也可以肄渗,喜歡的同學(xué)可以自己去探究
bsdiff
bsdiff是用來(lái)生成差分包的镇眷,可以通過(guò)如下命令來(lái)生成
C:\Users\XXX\Desktop\bsdiff>bsdiff old.apk new.apk patch.apk
介紹下上面命令的用法:
bsdiff:固定寫(xiě)法
old.apk:舊文件名稱
new.apk: 新文件名稱
patch.apk :生成的差分包名稱,可隨便取名
最終生成
old翎嫡、new是我們的歷史版本與最新版本欠动,patch.apk就是我們生成的目標(biāo)文件
bspatch
下面介紹下,我們Android端怎么使用bspatch來(lái)合成我們的安裝包惑申,上面演示的是在windows環(huán)境下生成差分包具伍,但我們Android是基于linux的,自然不能使用exe文件圈驼,我們得把源碼拿過(guò)來(lái)在我們的App內(nèi)生成so庫(kù)再使用人芽。關(guān)于NDK基礎(chǔ)部分我們略過(guò)。
1.新建c/c++工程绩脆,并把源碼拷貝過(guò)來(lái)萤厅,配置好cmake文件
2.編寫(xiě)native方法
其中圖中的executePatch方法為源文件中的main方法,只是這里為了方便辨識(shí)靴迫,給改了個(gè)名字而已
3.合成差分包并安裝
最終在activity中調(diào)用patch方法即可進(jìn)行安裝包的合成
patch包在這里由手動(dòng)放在data/data/packagename/cache/目錄下的來(lái)模擬從服務(wù)器請(qǐng)求的情況惕味,app.apk即為我們生成的目標(biāo)文件,通過(guò)安裝它來(lái)更新App
demo源碼鏈接如下:
https://github.com/xuchengpu/BSPatch.git
Dex文件簡(jiǎn)析
Dex文件是Android系統(tǒng)的可執(zhí)行文件玉锌,包含應(yīng)用程序的全部操du作指令以及運(yùn)行時(shí)數(shù)據(jù)赦拘。 當(dāng)java程序編譯成class后,還需要使用dx工具將所有的class文件整合到一個(gè)dex文件芬沉,目的是其中各個(gè)類能夠共享 數(shù)據(jù),在一定程度上降低了冗余阁猜,同時(shí)也使文件結(jié)構(gòu)更加緊湊丸逸,實(shí)驗(yàn)表明,dex文件是傳統(tǒng)jar文件大小的50%左 右剃袍。dex 文件可以分為3個(gè)模塊黄刚,頭文件、索引區(qū)民效、數(shù)據(jù)區(qū)憔维。頭文件概況的描述了整個(gè) dex 文件的分布涛救,包括每一個(gè)索 引區(qū)的大小跟偏移。索引區(qū)表示每個(gè)數(shù)據(jù)的標(biāo)識(shí)业扒,索引區(qū)主要是指向數(shù)據(jù)區(qū)的偏移检吆。
從圖中可以看出,像String_ids程储、Type_ids等這些每個(gè)文件共有的信息蹭沛,都被整合到一起,減少文件體積大小章鲤。
我們可以使用010Editor查看工具打開(kāi)一個(gè)dex來(lái)同步分析摊灭。
Header
是dex文件的頭部,記錄整個(gè)dex文件的相關(guān)屬性败徊,長(zhǎng)度為112個(gè)字節(jié)帚呼。
頭文件里包含以下部分:
magic(魔數(shù)):每個(gè)文件的頭文件里前8個(gè)字節(jié),代表文件的格式
checksum: 文件校驗(yàn)碼皱蹦,使用 alder32 算法校驗(yàn)文件除去 maigc煤杀、checksum 外余下的所有文件區(qū)域,用于 檢 查文件錯(cuò)誤根欧。 signature: 使用 SHA-1 算法 hash 除去 magic怜珍、checksum 和 signature 外余下的所有文件區(qū)域, 用于唯一 識(shí)別本文件 凤粗。 file_size: dex 文件大小 header_size: header 區(qū)域的大小酥泛,固定為 0x70 endian_tag: 大小端標(biāo)簽,dex 文件格式為小端嫌拣,固定值為 0x12345678 map_off: map_item 的偏移地址柔袁,該 item 屬于 data 區(qū)里的內(nèi)容,值要大于等于 data_off 的大小异逐,處于 dex 文件的末端捶索。
其他 xx_off , xx_size 成對(duì)出現(xiàn)灰瞻,表示數(shù)據(jù)的偏移與數(shù)據(jù)個(gè)數(shù)腥例。
這里以16進(jìn)制方式來(lái)查看magic為例:
這幾個(gè)數(shù)值轉(zhuǎn)換為字符串為dex.035,被稱為文件簽名。dex代表文件格式酝润,035代表版本號(hào)燎竖。
索引區(qū)
StringIds : 描述了 dex 文件中所有的字符串。記錄的數(shù)據(jù)只有一個(gè)偏移量要销,偏移量指向了 數(shù)據(jù)區(qū)Data中 的一 個(gè)字符串
type_ids : 類似數(shù)據(jù)索引构回,記錄了每個(gè)類型的字符串索引
proto_ids : 原型數(shù)據(jù)索引,記錄了方法聲明的字符串,返回類型字符串纤掸,參數(shù)列表
field_ids : 字段數(shù)據(jù)索引脐供,記錄了所屬類,類型以及方法名
method_ids :類方法索引借跪,記錄方法所屬類名政己,方法聲明以及方法名等信息
class_defs :類定義數(shù)據(jù)索引,記錄指定類各類信息垦梆,包括接口匹颤,超類,類數(shù)據(jù)偏移量
數(shù)據(jù)區(qū)
保存了各個(gè)類的真實(shí)數(shù)據(jù)