Android 增量更新的實(shí)現(xiàn)

扯淡

最近閑來(lái)無(wú)事搀继,學(xué)習(xí)了一下增量更新窘面。

增量更新的概念就不扯了,有興趣的看一下鴻洋大神的文章Android 增量更新完全解析 是增量不是熱修復(fù)叽躯。

測(cè)試設(shè)備(Android 5.0系統(tǒng))

Talk is cheap财边!廢話不多說(shuō),接下來(lái)開始踩坑之路点骑。

準(zhǔn)備工具

  • bsdiff/bzip 密碼: qdrb

    • 下載 bzip 后解壓把里面的 .c 和 .h 文件復(fù)制到項(xiàng)目 app/src/main/jni/ 下面
    • bsdiff 文件中的 bsdiff.c 和 bspatch.c 文件復(fù)制到項(xiàng)目 app/src/main/jni/ 下面
  • Android Studio 配置 NDK 環(huán)境 Android NDK 開發(fā)從 0 到 1

生成增量文件

  • 寫一個(gè)工具類 DiffUtil.java
    static {
        System.loadLibrary("bsdiff");
    }

    /**
     * native 方法 比較路徑為 oldPath 的 apk 與 newPath 的 apk 之間差異酣难,并生成 patch 包,存儲(chǔ)于 patchPath
     */
    public static native int genDiff(String oldApkPath, String newApkPath, String patchPath);
  • 生成頭文件
 在 Terminal 中進(jìn)入到項(xiàng)目 ..app\src\main\java> 下輸入 javah -d ../jni  包名.方法名

如: javah -d ../jni sj.updateplus_utils.DiffUtil
  • 復(fù)制頭文件中代碼到 bsdiff.c 中黑滴,之后再添加如下代碼
JNIEXPORT jint JNICALL Java_sj_updateplus_utils_DiffUtil_genDiff
                 (JNIEnv *env, jclass cls, jstring old, jstring new, jstring patch) {
    int argc = 4;
    char * argv[argc];
    argv[0] = "bsdiff";
    argv[1] = (char*) ((*env)->GetStringUTFChars(env, old, 0));
    argv[2] = (char*) ((*env)->GetStringUTFChars(env, new, 0));
    argv[3] = (char*) ((*env)->GetStringUTFChars(env, patch, 0));

    printf("old apk = %s \n", argv[1]);
    printf("new apk = %s \n", argv[2]);
    printf("patch = %s \n", argv[3]);

    int ret = diffMain(argc, argv);

    printf("genDiff result = %d ", ret);

    (*env)->ReleaseStringUTFChars(env, old, argv[1]);
    (*env)->ReleaseStringUTFChars(env, new, argv[2]);
    (*env)->ReleaseStringUTFChars(env, patch, argv[3]);

    return ret;
}
  • bsdiff.c 中還需要修改的地方
//原代碼:
int main(int argc, char *argv[]) {
    ...
}
//修改為:
int diffMain(int argc, char *argv[]) {
    ...
}
//原代碼
#include <bzlib.h>
//修改為,可自定義
#include "bzip2/bzlib.h"

最后再進(jìn)行編譯運(yùn)行憨募,這期間可能遇到各種報(bào)錯(cuò),哈哈袁辈,沒(méi)關(guān)系菜谣,反正我也不知道怎么解決。(???開玩笑,后面有踩坑經(jīng)歷)

增量文件和 oldApk 的合并

這個(gè)和增量文件的生成類似

  • 寫一個(gè)工具類 PatchUtil.java
    static {
        System.loadLibrary("bsdiff");
    }

    /**
     * native 方法 合并舊 apk 和補(bǔ)丁 patch尾膊,生成新的 apk
     * @param oldApkPath 舊apk文件路徑
     * @param newApkPath 合并生成的新 apk 保存路徑
     * @param patchPath  增量文件路徑
     * @return 合并結(jié)果: 0-成功 -其他失敗
     */
    public static native int mypatch(String oldApkPath, String newApkPath, String patchPath);`
  • 生成頭文件
    同增量文件的生成里面一樣
在 Terminal 中進(jìn)入到項(xiàng)目 ..app\src\main\java> 下輸入 javah -d ../jni  包名.方法名

如:javah -d ../jni sj.updateplus_utils.PatchUtil
  • 復(fù)制頭文件中代碼到 bspatch.c 里添加以下代碼
JNIEXPORT jint JNICALL Java_sj_updateplus_utils_PatchUtil_mypatch
        (JNIEnv *env, jclass cls,
         jstring old, jstring new, jstring patch) {
    int argc = 4;
    char *argv[argc];
    argv[0] = "bspatch";
    argv[1] = (char *) ((*env)->GetStringUTFChars(env, old, 0));
    argv[2] = (char *) ((*env)->GetStringUTFChars(env, new, 0));
    argv[3] = (char *) ((*env)->GetStringUTFChars(env, patch, 0));

    int ret = patchMain(argc, argv);

    (*env)->ReleaseStringUTFChars(env, old, argv[1]);
    (*env)->ReleaseStringUTFChars(env, new, argv[2]);
    (*env)->ReleaseStringUTFChars(env, patch, argv[3]);
    return ret;
}
  • bspatch.c 中還需要修改的地方
//原代碼
int main(int argc, char *argv[]) {
    ...
}
//修改為,可自定義
int patchMain(int argc, char *argv[]) {
    ...
}
//原代碼:
#include <bzlib.h>
//修改為:
#include "bzip2/bzlib.h"

踩過(guò)的坑

  • 編譯缺少 xxx 文件
    CMakeLists.txt 文件中添加以下代碼
add_library( # Sets the name of the library.
             bsdiff

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/jni/bzip2/blocksort.c
             src/main/jni/bzip2/bzip2.c
             src/main/jni/bzip2/bzip2recover.c
             src/main/jni/bzip2/bzlib.c
             src/main/jni/bzip2/compress.c
             src/main/jni/bzip2/crctable.c
             src/main/jni/bzip2/decompress.c
             src/main/jni/bzip2/dlltest.c
             src/main/jni/bzip2/huffman.c
             src/main/jni/bzip2/mk251.c
             src/main/jni/bzip2/randtable.c
             src/main/jni/bzip2/spewG.c
             src/main/jni/bzip2/unzcrash.c
             src/main/jni/bsdiff.c
             src/main/jni/bspatch.c )

CMakeLists.txt 中這兩處地方要一致媳危,可自定義

add_library( # Sets the name of the library.
             bsdiff
             ... )

target_link_libraries( # Specifies the target library.
                       bsdiff
                      ...)
  • 可能需要添加
    gradle.properties 文件
android.useDeprecatedNdk=true

進(jìn)行 MD5 驗(yàn)證

這個(gè)步驟是為了檢驗(yàn)合并生成的 apk 文件和我們要升級(jí)更新的 apk 文件是否一樣
在 apk 文件目錄下打開 cmd
輸入命令行

//***.apk 為需要驗(yàn)證的 apk 文件名
certutil -hashfile ***.apk MD5
image.png

寫在最后

到這邊增量更新操作基本就完成了。還有一些考慮不足之處冈敛。
當(dāng)然這只是進(jìn)行了增量文件的生成和新 apk 的合并待笑,而且也只是在本地進(jìn)行。其實(shí)呢莺债,增量文件的生成最好在服務(wù)端進(jìn)行滋觉,而且需要生成多個(gè)版本與最新版本的增量文件,才能保證各個(gè)版本的用戶可以正常更新;更新完后還要安裝等齐邦。
筆者這里是對(duì)其他 apk 的增量更新椎侠,如果是對(duì)本身 apk 的更新的話,還需要提取自身 apk 之類的措拇,其他步驟可參照以上所寫我纪。

第一次寫文章,還望各位指點(diǎn)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末丐吓,一起剝皮案震驚了整個(gè)濱河市浅悉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌券犁,老刑警劉巖术健,帶你破解...
    沈念sama閱讀 216,744評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異粘衬,居然都是意外死亡荞估,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門稚新,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)勘伺,“玉大人,你說(shuō)我怎么就攤上這事褂删》勺恚” “怎么了?”我有些...
    開封第一講書人閱讀 163,105評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵屯阀,是天一觀的道長(zhǎng)缅帘。 經(jīng)常有香客問(wèn)我,道長(zhǎng)难衰,這世上最難降的妖魔是什么股毫? 我笑而不...
    開封第一講書人閱讀 58,242評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮召衔,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘祭陷。我一直安慰自己苍凛,他們只是感情好趣席,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,269評(píng)論 6 389
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著醇蝴,像睡著了一般宣肚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上悠栓,一...
    開封第一講書人閱讀 51,215評(píng)論 1 299
  • 那天霉涨,我揣著相機(jī)與錄音,去河邊找鬼惭适。 笑死笙瑟,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的癞志。 我是一名探鬼主播往枷,決...
    沈念sama閱讀 40,096評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼凄杯!你這毒婦竟也來(lái)了错洁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,939評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤戒突,失蹤者是張志新(化名)和其女友劉穎屯碴,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體膊存,經(jīng)...
    沈念sama閱讀 45,354評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡导而,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,573評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了膝舅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗡载。...
    茶點(diǎn)故事閱讀 39,745評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖仍稀,靈堂內(nèi)的尸體忽然破棺而出洼滚,到底是詐尸還是另有隱情,我是刑警寧澤技潘,帶...
    沈念sama閱讀 35,448評(píng)論 5 344
  • 正文 年R本政府宣布遥巴,位于F島的核電站,受9級(jí)特大地震影響享幽,放射性物質(zhì)發(fā)生泄漏铲掐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,048評(píng)論 3 327
  • 文/蒙蒙 一值桩、第九天 我趴在偏房一處隱蔽的房頂上張望摆霉。 院中可真熱鬧,春花似錦、人聲如沸携栋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)婉支。三九已至鸯隅,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間向挖,已是汗流浹背蝌以。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留何之,地道東北人跟畅。 一個(gè)月前我還...
    沈念sama閱讀 47,776評(píng)論 2 369
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像帝美,于是被迫代替她去往敵國(guó)和親碍彭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,652評(píng)論 2 354

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

  • 增量更新在Android開發(fā)中是一種很常見的技術(shù)。 增量更新的原理 增量更新的原理非常簡(jiǎn)單舰褪,就是將本地apk與服務(wù)...
    re冷星閱讀 1,570評(píng)論 3 3
  • 最近就是在練習(xí)ndk開發(fā)皆疹,剛好遇到android增量更新的話題,主要是工具的運(yùn)用占拍,略帶使用第三方so庫(kù)的流程~~~...
    紅黑軍團(tuán)號(hào)閱讀 553評(píng)論 1 3
  • 注:首發(fā)地址 0. 前言 如果只學(xué)理論略就,不做實(shí)踐,不踩踩坑晃酒,一般很難發(fā)現(xiàn)真正實(shí)踐項(xiàng)目中的問(wèn)題的表牢,也比較難以加深對(duì)技...
    cfanr閱讀 9,490評(píng)論 4 50
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,083評(píng)論 25 707
  • 小餅干本干閱讀 334評(píng)論 7 12