淺談Android增量更新客戶(hù)端的實(shí)現(xiàn)方法

因?yàn)轫?xiàng)目需要前兩天研究了下增量更新的,如果項(xiàng)目沒(méi)有硬性規(guī)定的話(huà),本人推薦使用第三方的SDK.

比如:友盟的增量更新SDK 傳送門(mén)http://www.umeng.com/component_update分分鐘就能實(shí)現(xiàn)Android增量更新功能,友盟官方API相信大家都能看懂,不懂的沒(méi)關(guān)系之后我也會(huì)單獨(dú)寫(xiě)個(gè)用友盟的Demo

//TODO 友盟Demo傳送門(mén):

如果你跟我一樣,項(xiàng)目硬性規(guī)定必須自己寫(xiě)增量更新的代碼,請(qǐng)往下看下面的

●功能版本:

增量更新是Google 4.1增加的新功能

●官方說(shuō)明

[html]view plaincopy

Smart?app?updates?is?a?new?feature?of?Google?Play?that?introduces?a?better?way?of?delivering?app?updates?to?devices.?When?developers?publish?an?update,?Google?Play?now?delivers?only?the?bits?that?have?changed?to?devices,?rather?than?the?entire?APK.?This?makes?the?updates?much?lighter-weight?in?most?cases,?so?they?are?faster?to?download,?save?the?device’s?battery,?and?conserve?bandwidth?usage?on?users’?mobile?data?plan.?On?average,?a?smart?app?update?is?about?1/3?the?sizeof?a?full?APK?update.

http://developer.android.com/about/versions/jelly-bean.html

●功能背景:

現(xiàn)在的安卓Apk越來(lái)越大本冲,而在此之前如果用戶(hù)發(fā)現(xiàn)有新版本的話(huà)昵仅,需要重新把對(duì)應(yīng)程序的新版本下載下來(lái)轿曙,有時(shí)候并不是重大更新,僅僅只是優(yōu)化了一下,用戶(hù)就需要重新下載apk缩筛,不僅浪費(fèi)流量而且浪費(fèi)時(shí)間(等同于浪費(fèi)生命啊,親!!!),有這樣的問(wèn)題,便會(huì)出現(xiàn)更優(yōu)的功能迭代即增量更新或增量升級(jí)堡称,或者叫差異化更新瞎抛,目前很多應(yīng)用商店已經(jīng)對(duì)接了此功能:比如谷歌官方,小米等等却紧。桐臊。胎撤。

●實(shí)現(xiàn)原理:

客戶(hù)端與服務(wù)端對(duì)比,并生成版本之間的差異包,用戶(hù)不用下載整個(gè)apk文件,只用下載差異包就可以了豪硅,比如用戶(hù)微博2.0升級(jí)到微博3.0哩照,本來(lái)微博3.0版本應(yīng)該是10M,服務(wù)器通過(guò)生成差異包4M懒浮,用戶(hù)直接下載4M文件并在本地進(jìn)行合并生成微博3.0版本飘弧,安裝,對(duì)于網(wǎng)絡(luò)環(huán)境較差的用戶(hù)絕對(duì)提高用戶(hù)體驗(yàn),節(jié)省流量和時(shí)間

(服務(wù)端+客戶(hù)端)實(shí)現(xiàn)思路:

1.客戶(hù)端帶著VerisionCode發(fā)送請(qǐng)求給服務(wù)端

2.服務(wù)端判斷VersionCode是否是最新版本,如果不是檢測(cè)是否有此版本和最新版本的差異包,如果沒(méi)有則在后臺(tái)生成(舊VersionCode-新VersionCode).patch文件

3.客戶(hù)端收到返回?cái)?shù)據(jù),判斷是否最新,如果不是彈出升級(jí)的Dilog對(duì)話(huà)框

4.點(diǎn)擊立即升級(jí),再次發(fā)送請(qǐng)求

5.服務(wù)端返回給客戶(hù)端對(duì)應(yīng)版本差異包的Url地址

6.客戶(hù)端拿到URL地址下載到SD卡中,并從客戶(hù)端data/app 目錄下拷貝本程序的apk安裝包,

7.客戶(hù)端通過(guò)調(diào)用JNI編譯的.so動(dòng)態(tài)鏈接庫(kù)中的方法合并舊版本和差異包,生成新版本,調(diào)用Intent方法安裝最新的apk包

用到的知識(shí)點(diǎn):

1.JNI相關(guān)(重點(diǎn))

2.Http協(xié)議相關(guān)(次重點(diǎn))

3.工廠設(shè)計(jì)模式_調(diào)用接口實(shí)現(xiàn)類(lèi)(次重點(diǎn))

●實(shí)現(xiàn)

假設(shè)砚著,你的apk已經(jīng)發(fā)布了3個(gè)版次伶,1.0,2.0稽穆,3.0冠王,這時(shí)候你要在后臺(tái)發(fā)布4.0,在你上傳時(shí)舌镶,就應(yīng)該生成

1.0——>4.0的差異包柱彻;

2.0——>4.0的差異包;

3.0——>4.0的差異包餐胀;

選擇使用這個(gè)開(kāi)源二進(jìn)制比較工具來(lái)實(shí)現(xiàn):

http://www.daemonology.net/bsdiff/

下載后得到bsdiff-4.3.tar.gz哟楷。

其中bsdiff.c是二進(jìn)制文件比對(duì)的代碼;bspatch.c是二進(jìn)制文件合成的代碼否灾;

我們將使用這個(gè)bsdiff來(lái)生成兩個(gè)apk的patch包卖擅,并且使用bspatch.c來(lái)合成舊apk與patch包;

使用bsdiff墨技、bspatch時(shí)惩阶,還需用到bzip2: http://www.bzip.org/downloads.html

下載后得到:bzip2-1.0.6.tar.gz。

我們需要用到bzip2-1.0.6.tar.gz中以下13個(gè)文件(這里面可能有的是不需要的扣汪,我都拷貝過(guò)來(lái)了):

[plain]view plaincopy

01?blocksort.c

02?bzip2.c

03?bzip2recover.c

04?bzlib_private.h

05?bzlib.c

06?bzlib.h

07?compress.c

08?crctable.c

09?decompress.c

10?dlltest.c

11?huffman.c

12?randtable.c

13?spewG.c

將這13個(gè)文件拷貝至jni目錄下断楷,接下來(lái),我們就調(diào)用bsdiff生成差異包私痹,并且調(diào)用bspatch合成新包脐嫂。

客戶(hù)端解決問(wèn)題:

1)??????在客戶(hù)端把下載的.patch(差異包) 與舊版apk就行合并

一.??獲取舊版本apk

[java]view plaincopy

/**

*?備份data/app目錄下本程序的apk安裝文件到SD卡根目錄下

*?@param?packageName

*?@param?mActivity

*?@throws?IOException

*/

publicstaticvoidbackupApp(String?packageName,?Activity?mActivity)

throwsIOException?{

//存放位置

StringnewFile?=?Environment.getExternalStorageDirectory()

.getAbsolutePath()+?File.separator;

StringoldFile?=null;

try{

//原始位置

oldFile=?mActivity.getPackageManager().getApplicationInfo(

packageName,0).sourceDir;

}catch(NameNotFoundException?e)?{

e.printStackTrace();

}

System.out.println(newFile);

System.out.println(oldFile);

Filein?=newFile(oldFile);

Fileout?=newFile(newFile?+?packageName?+".apk");

if(!out.exists())?{

out.createNewFile();

Log.i(tag,"文件備份成功!"+"存放于"+?newFile?+"目錄下");

}else{

Log.i(tag,"文件備份成功紊遵!"+"存放于"+?newFile?+"目錄下");

}

FileInputStreamfis?=newFileInputStream(in);

FileOutputStreamfos?=newFileOutputStream(out);

intcount;

//文件太大的話(huà)账千,我覺(jué)得需要修改

byte[]buffer?=newbyte[256*1024];

while((count?=?fis.read(buffer))?>0)?{

fos.write(buffer,0,?count);

}

fis.close();

fos.flush();

fos.close();

}

二.??合并差異包和舊版本APK

[java]view plaincopy

/**

*?顯示更新對(duì)話(huà)框

*/

protectedvoid?showUpdateDialog()?{

AlertDialog.Builderbuilder?=newBuilder(this);

builder.setTitle("更新提醒");

builder.setMessage("1.增加數(shù)據(jù)庫(kù)...");

builder.setOnCancelListener(newOnCancelListener()?{

@Override

publicvoid?onCancel(DialogInterface?dialog)?{

}

});

builder.setPositiveButton("立刻升級(jí)",newDialogInterface.OnClickListener()?{

@Override

publicvoid?onClick(DialogInterface?dialog,intwhich)?{

Log.i(tag,"下載最新版本:"+",替換安裝");

finalProgressDialog?pd?=newProgressDialog(

MainActivity.this);

pd.setTitle("更新提醒:");

pd.setMessage("正在下載更新apk");

//顯示指定水平方向的進(jìn)度條

pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

pd.show();

if(Environment.getExternalStorageState().equals(

Environment.MEDIA_MOUNTED)){

newThread()?{

publicvoid?run()?{

Filef?=newFile(Environment

.getExternalStorageDirectory(),"temp.patch");

//獲取服務(wù)器上生成的差異包地址result

//??????????????????????????????????????????????????????????????PatcherEngineengine?=?BeanFactory.getInstance(PatcherEngine.class);

//??????????????????????????????????????????????????????????????Stringresult?=?engine.getUpGrade(MainActivity.this);

Filefile?=null;

//??????????????????????????????????????????????????????????????if(result!=null){

file=?DownloadManager.download(

urlPath,

f.getAbsolutePath(),pd);

//???????????????????????????????????????????????????????????????????????Log.i(tag,result);

//??????????????????????????????????????????????????????????????}

if(file?==null)?{

Log.i(tag,"下載的文件不存在");

}else{

Log.i(tag,"下載成功替換安裝");

try{

//這里的包名com.dodola.patcher就是你要從data/app目錄下復(fù)制出來(lái)的舊版apk包

ApkInfoTool.backupApp("com.dodola.patcher",MainActivity.this);

}catch(IOException?e)?{

//TODO?Auto-generated?catch?block

e.printStackTrace();

}

Stringpatch?=?rootPath?+?File.separator?+"temp.patch";

StringnewApk?=?rootPath?+?File.separator?+"new.apk";

//這里的包名com.dodola.patcher改成你自己的包名,不然肯定是不能合并的

StringoldApk?=?rootPath?+?File.separator?+"com.dodola.patcher.apk";

//合并差異文件和舊版APK包得到新版APk

patcher(oldApk,newApk,?patch);

//安裝新版APK

installApk(newApk);

}

pd.dismiss();

};

}.start();

}else{

Toast.makeText(getApplicationContext(),"sd卡不可用",0).show();

}

}

});

builder.setNegativeButton("下次再說(shuō)",newDialogInterface.OnClickListener()?{

@Override

publicvoid?onClick(DialogInterface?dialog,intwhich)?{

Toast.makeText(getApplicationContext(),"下次再說(shuō)",0).show();

}

});

builder.show();

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市暗膜,隨后出現(xiàn)的幾起案子匀奏,更是在濱河造成了極大的恐慌,老刑警劉巖学搜,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件娃善,死亡現(xiàn)場(chǎng)離奇詭異论衍,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)聚磺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)坯台,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人瘫寝,你說(shuō)我怎么就攤上這事蜒蕾。” “怎么了焕阿?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵咪啡,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我暮屡,道長(zhǎng)撤摸,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任褒纲,我火速辦了婚禮准夷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘莺掠。我一直安慰自己冕象,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布汁蝶。 她就那樣靜靜地躺著,像睡著了一般论悴。 火紅的嫁衣襯著肌膚如雪掖棉。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天膀估,我揣著相機(jī)與錄音幔亥,去河邊找鬼。 笑死察纯,一個(gè)胖子當(dāng)著我的面吹牛帕棉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播饼记,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼香伴,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了具则?” 一聲冷哼從身側(cè)響起即纲,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎博肋,沒(méi)想到半個(gè)月后低斋,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蜂厅,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年膊畴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了掘猿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡唇跨,死狀恐怖稠通,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情轻绞,我是刑警寧澤采记,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站政勃,受9級(jí)特大地震影響唧龄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜奸远,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一既棺、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧懒叛,春花似錦丸冕、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至檩奠,卻和暖如春掐松,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背罢杉。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工趟畏, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人滩租。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓赋秀,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親律想。 傳聞我的和親對(duì)象是個(gè)殘疾皇子猎莲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容